/* Copyright 2023 Finalkey
 * Copyright 2023 LiWenLiu <https://github.com/LiuLiuQMK>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "quantum.h"
#include "usb_descriptor.h"
#include "User_Infomation_Define.h"
#include "usb_main.h"
#include "raw_hid.h"

#define WHEEL_ZA_IO         (B2)
#define WHEEL_ZB_IO         (B10)

#define MAC_WIN_IO          (B14)
#define MODE_2P4G_IO        (B12)
#define MODE_BLE_IO         (B13)

#define ES_BATT_STDBY_IO    (A13)
#define ES_USB_POWER_IO     (C5)
#define ES_SPI_ACK_IO       (A4)
#define ES_PWM_DMA_IO       (A2)

#define ES_WUKEUP_IO        (D1)
#define ES_SDB_POWER_IO     (A3)
#define ES_LED_POWER_IO     (D0)

void U16_Buff_Clear(uint16_t *Buff, uint8_t Len) {
    for(uint8_t i = 0; i < Len; i++) {
        Buff[i] = 0;
    }
}

extern int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len);

void es_spi_send_recv_by_dma(uint32_t num, uint8_t *rx_buf, uint8_t *tx_buf);
void User_bluetooth_send_keyboard(uint8_t *report, uint32_t len);

uint8_t es_keyboard_leds(void);
void    es_send_keyboard(report_keyboard_t *report);
void    es_send_nkro(report_nkro_t *report);
void    es_send_mouse(report_mouse_t *report);
void    es_send_extra(report_extra_t *report);

volatile host_driver_t * es_qmk_driver = NULL;
const host_driver_t es_user_driver  = {es_keyboard_leds, es_send_keyboard, es_send_nkro, es_send_mouse, es_send_extra};

/************************电池**************************/
uint16_t User_Adc_Batt[USER_BATT_SCAN_COUNT] = {0};  // 存储电池电压ADC读数
uint16_t User_Scan_Batt[USER_BATT_SCAN_COUNT] = {0}; // 存储电压读数
uint8_t User_Adc_Batt_Count = 0U;                    // 记录采集了多少次电池电压数据
uint8_t User_Batt_BaiFen = 0U;                       // 存储电池电量百分比
uint8_t User_Batt_Old_BaiFen = 0U;                   // 存储上一次电池电量百分比
uint8_t User_Batt_10ms_Count = 0x00;                 // 定时器
uint16_t User_Batt_Time_15S_Count = 0U;              // 15S触发一次事件
bool User_Batt_Power_Up = false;                     // 是否处于上电启动状态
bool User_Batt_Send_Spi = false;                     // 是否需要通过SPI接口发送相关信息
uint16_t User_Batt_Power_Up_Delay_100ms_Count = 0U;  // 上电延迟100ms再去采集电量
bool User_Batt_Power_Up_Delay = false;               // 上电延迟是否完成

bool User_Power_Low = false;                         // 电池电量低于某个阈值
uint8_t User_Power_Low_Count = 0U;                   // 记录低电量状态持续时间次数
uint8_t es_stdby_pin_state = 0U;                     // 充电状态

bool User_Key_Batt_Num_Show = false;                 // 电量查询标志位
uint16_t User_Key_Batt_Count = 0;                    // 按键操作请求显示电池信息
bool User_Key_Batt_Num_Flag = false;
bool User_Key_Batt_LED_Flag = false;
/*********************************************************/

/************************SPI******************************/
volatile uint8_t Spi_Send_Recv_Flg = 0U;             // 标志，表示当前是否有 SPI 发送或接收在进行
uint8_t g_es_spi_rx_buf[64], g_es_spi_tx_buf[64];    // 存放从 SPI 设备接收到的数据和存放要通过 SPI 发送的数据
uint8_t Repet_Send_Count = 0x00;                     // 记录重复发送的次数，初始值为0x00，表示还没有进行过重复发送,，如果第一次发送失败，可能需要重新发送数据
uint8_t Send_Key_Type = SPI_NACK;                    // 表示发送的键类型，初始值为 SPI_NACK，表示初始状态下发送的是 NACK 信号
/*********************************************************/

/************************Keyboard Info********************/
Keyboard_Info_t Keyboard_Info = {
    .Key_Mode = INIT_WORK_MODE,         // 键盘工作模式
	.Key_Mode_Old = INIT_WORK_MODE,     // 键盘上一次工作模式
    .Ble_Channel = INIT_BLE_CHANNEL,    // 蓝牙通道
    .Batt_Number = INIT_BATT_NUMBER,    // 电池电量
    .Nkro = INIT_ALL_SIX_KEY,           // 六键全键无冲
    .Mac_Win_Mode = INIT_WIN_MAC_MODE,  // MAC系统WIN系统
    .Win_Lock = INIT_WIN_LOCK_NLOCK,    // 锁WIN
    .Led_On_Off = INIT_LED_ON_OFF,      // 背光开关
#if LOGO_LED_ENABLE
    .Logo_On_Off = INIT_LOGO_ON_OFF,         // LOGO灯光开关
    .Logo_Mode = INIT_LOGO_MODE,             // LOGO灯光模式
    .Logo_Colour = INIT_LOGO_COLOUR,         // LOGO灯光颜色
    .Logo_Saturation = INIT_LOGO_SATURATION, // LOGO灯光饱和度
    .Logo_Brightness = INIT_LOGO_BRIGHTNESS, // LOGO灯光亮度
    .Logo_Speed = INIT_LOGO_SPEED,           // LOGO灯光速度
#endif
#if SIDE_LED_ENABLE
    .Side_On_Off = INIT_SIDE_ON_OFF,         // 测灯灯光开关
    .Side_Mode = INIT_SIDE_MODE,             // 测灯灯光模式
    .Side_Colour = INIT_SIDE_COLOUR,         // 测灯灯光颜色
    .Side_Saturation = INIT_SIDE_SATURATION, // 测灯灯光饱和度
    .Side_Brightness = INIT_SIDE_BRIGHTNESS, // 测灯灯光亮度
    .Side_Speed = INIT_SIDE_SPEED,           // 测灯灯光速度
#endif
};

Keyboard_Status_t Keyboard_Status = {  // 键盘状态信息
    .System_Work_Status = 0x00,        // 系统工作状态
    .System_Work_Mode = 0x00,          // 系统工作模式
    .System_Work_Channel = 0x00,       // 系统工作通道
    .System_Connect_Status = 0x00,     // 系统连接状态
    .System_Led_Status = 0x00,         // LED状态
    .System_Sleep_Mode = 0x00          // 系统睡眠模式
};

bool Key_2p4g_Status = false;           // 2.4G的状态
bool Key_Ble_1_Status = false;          // 三个不同的蓝牙的状态
bool Key_Ble_2_Status = false;          
bool Key_Ble_3_Status = false;          
bool Key_Fn_Status = false;             // 功能键（Fn）的状态

bool Init_Spi_Power_Up = true;          // SPI上电时初始化
uint8_t Init_Spi_100ms_Delay = 0;       // 存储SPI初始化时所需的100毫秒延迟计数器

bool Led_Rf_Pair_Flg = false;           // RF配对过程中的LED状态
uint8_t Temp_System_Led_Status = 0xff;  // 临时存储系统的LED状态
uint8_t Led_Point_Count = 0U;
uint8_t Mac_Win_Point_Count = 0U;

uint16_t Usb_Suspend_Delay = 0;         // 存储USB进入挂起状态前的延迟时间

uint8_t Key_Mac_Win_Scan = 0x00;
uint8_t Key_Mac_Win_Check = 0x00;
uint8_t Key_Mac_Win_Old = 0x00;
uint8_t Key_Mac_Win_delay = 0x00;

uint8_t Key_Switch_Scan = 0x00;         // 扫描按键开关的状态
uint8_t Key_Switch_Check = 0x00;        // 检查按键开关的状态
uint8_t Key_Switch_Old = 0x00;          // 存储上一次按键开关的状态
uint8_t Key_Switch_delay = 0x00;        // 按键开关处理的延迟计数器

uint16_t Usb_Change_Mode_Delay = 0;
bool Usb_Change_Mode_Wakeup = false;
bool Mode_Synchronization_Signal = false;

bool Save_Flash = false;
bool Reset_Save_Flash = false;
uint16_t Save_Flash_3S_Count = 0;
bool Led_Flash_Busy = false;

bool Led_Off_Start = false;
bool Led_Power_Up = false;
uint16_t Led_Power_Up_Delay = 0;

bool Led_Point_Sleep = false;
bool Usb_If_Ok_Led = false;
bool Usb_If_Ok = false;
uint16_t Usb_If_Ok_Delay = 0;
uint16_t g_usb_sof_frame_id = 0;
uint16_t g_usb_sof_frame_id_last = 0;
bool Usb_Dis_Connect = false;

bool Ble_Name_Spi_Send = false;
uint8_t Ble_Name_Spi_Count = QMK_BLE_CHANNEL_1;
/************************键盘恢复初始化变量*******************/
uint16_t Time_3s_EE_CLR_Count = 0;
bool User_QMK_EE_CLR_Flag = false;
bool User_EE_CLR_Start_Flag = false;
/*********************************************************/

/************************Systick**************************/
uint8_t Systick_6ms_Count = 0U;
uint8_t Systick_10ms_Count = 0x00;
uint8_t Systick_10s_Count = 0x00;
uint16_t Systick_Interval_Count = 0x00;
uint8_t Systick_Led_Count = 0x00;
uint8_t Batt_Led_Count = 0x00;
uint16_t Time_3s_Count = 0;
uint16_t Spi_Interval = SPI_DELAY_RF_TIME;
/*********************************************************/

/************************数据队列**************************/
static uint8_t app_2g4_data[APP_2G4_BUF_CNT][APP_2G4_BUF_SIZE]; // 初始化环形缓冲区，缓冲区元素的数量(即缓冲区的深度)和元素的大小
static volatile uint8_t app_2g4_data_send = 0;      // 初始化发送读取索引位置
static volatile uint8_t app_2g4_data_rev = 0;       // 初始化接收写入索引位置

static uint8_t app_2g4_buffer_full(void) {          // 判断缓冲区是否已满
    uint8_t tmp_rev = app_2g4_data_rev + 1;         // 下一个写入的位置等于读取位置则缓冲区满
    if(tmp_rev == APP_2G4_BUF_CNT)                  // 达到最大容量时
    {
        tmp_rev = 0;                                // 循环回到缓冲区开始位置
    }
    return (tmp_rev == app_2g4_data_send);          // 相等则返回 true(非0值，这里是 uint8_t 类型)，表示下一个待写入的数据会覆盖未读取的数据；不等则返回 false(或者0)
}

static uint8_t app_2g4_buffer_empty(void) {         // 判断缓冲区是否为空
    return (app_2g4_data_rev == app_2g4_data_send); // 写入索引rev和读取索引 send 相等，说明缓存区没有未读取的数据 
}

static void app_2g4_buffer_rev_add(void) {          // 更新接收写入数据索引
    app_2g4_data_rev++;                             // 每次调用该函数时，接收写入索引＋1
    if(app_2g4_data_rev >= APP_2G4_BUF_CNT)         // 如果索引达到缓冲区最大容量
        app_2g4_data_rev = 0;                       // 则将索引重置为0，达到循环缓冲
}

static void app_2g4_buffer_send_add(void) {         // 更新发送读取数据索引
    app_2g4_data_send++;                            // 每次调用该函数时，发送读取索引＋1
    if(app_2g4_data_send >= APP_2G4_BUF_CNT)        // 如果索引达到缓冲区最大容量
        app_2g4_data_send = 0;                      // 则将索引重置为0，达到循环缓冲
}

/*轮询发送SPI按键数据函数*/
static void Spi_Main_Loop(void) {
    if (Init_Spi_Power_Up || Keyboard_Status.System_Work_Status) { // Init_Spi_Power_Up 如果为 true，表示 SPI 正在初始化上电过程中，此时不需要执行后续操作
        return;                                                    // Keyboard_Status.System_Work_Status 为非零值，表示系统工作在在某种状态，此时不需要执行任何操作
    }                                                              // 任一条件为真，则直接返回，不执行后续的 SPI 通信逻辑

    if ((!app_2g4_buffer_empty()) && (!Spi_Send_Recv_Flg) && (!gpio_read_pin(ES_SPI_ACK_IO))) {
        Spi_Send_Recv_Flg = 1;                                     // 将 Spi_Send_Recv_Flg 设置为1，表示现在有一个SPI发送/接收操作正在进行
        Send_Key_Type = SPI_NACK;                                  // 设置 Send_Key_Type 为无应答
        es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, app_2g4_data[app_2g4_data_send]);
        app_2g4_buffer_send_add();                                 // 调用 app_2g4_buffer_send_add 函数更新发送数据的索引，以便下次发送下一个数据包
    }
}
/*
!app_2g4_buffer_empty 表示缓存区不为空，可以发送数据；
!Spi_Send_Recv_Flg，如果 Spi_Send_Recv_Flg 为0，表示当前没有正在进行的SPI接收/发送操作；
!gpio_read_pin(ES_SPI_ACK_IO)，如果 ES_SPI_ACK_IO 引脚读取到低电平（0），表示已经准备好接收数据
调用 es_spi_send_recv_by_dma 函数通过DMA直接访问内存进行SPI数据的发送和接收
参数包括 USER_KEYBOARD_LENGTH，要发送的数据长度，g_es_spi_rx_buf 接收数据的缓存区，从 app_2g4_data 缓存区中获取当前要发送的数据包
*/
/*********************************************************/

/**************************EMI****************************/
bool Emi_Test_Start = false;                                   // 控制EMI测试是否开始，初始值为 false，表示尚未开始

void Emi_Init(void) {                                          // 初始化EMI测试相关的状态和标志
    Spi_Interval = SPI_DELAY_USB_TIME;                         // 设置SPI通信的间隔时间为 SPI_DELAY_USB_TIME
    Keyboard_Status.System_Work_Status = 0;                    // 将键盘工作状态重置为0
    Keyboard_Status.System_Sleep_Mode = 0;                     // 将键盘的睡眠模式重置为0
    Mode_Synchronization_Signal = false;                       // 将模式同步信号标志重置为 false
    Led_Rf_Pair_Flg = false;                                   // 将LED_RF配对标志重置为 false
    Ble_Name_Spi_Send = false;                                 // 将BLE名称发送标志重置为 false
}

void Emi_Read_Data(uint8_t *User_Data, uint8_t User_Length) {  // User_Data：指向要发送的数据的指针，User_Length：要发送的数据的长度
    if (Emi_Test_Start == false) {                             // 检查 Emi_Test_Start 是否为 false，如果是，直接返回
        return;
    }

    if (Init_Spi_Power_Up) {                                   // 检查 Init_Spi_Power_Up 是否为 true，如果是，直接返回
        return;
    }

    if (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO))) { // 检查 Spi_Send_Recv_Flg 是否为1或 ES_SPI_ACK_IO 引脚是否为高电平，如果是，则直接返回
        return;
    }

    Spi_Send_Recv_Flg = 1;                                     // 设置 Spi_Send_Recv_Flg 为1，表示正在进行SPI发送/接收操作
    Send_Key_Type = SPI_ACK;                                   // 设置 Send_Key_Type 为 SPI_ACK，表示发送应答信号
    Repet_Send_Count = 0;                                      // 重置 Repet_Send_Count 为0

    /*将需要发送的指令发送到680*/
    for (uint8_t i = 0; i < User_Length; i++) {                // 将 User_Data 中的数据复制到 g_es_spi_tx_buf 缓冲区中
        g_es_spi_tx_buf[i] = User_Data[i];
    }
    es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf); // 调用 es_spi_send_recv_by_dma 函数通过 DMA 进行 SPI 数据的发送和接收
    return;              // USER_KEYBOARD_LENGTH，要发送的数据长度，g_es_spi_rx_buf 接收数据的缓存区，从 app_2g4_data 缓存区中获取当前要发送的数据包
}

void Emi_Write_Data(uint8_t *User_Data, uint8_t User_Length) {  // 写入数据并通过 HID 发送
    if (Emi_Test_Start == false) {                              // 检查 Emi_Test_Start 是否为 false，如果是，直接返回
        return;
    }

    if (User_Data[0] == USER_KEYBOARD_COMMAND) {                // 检查 User_Data[0] 是否为 USER_KEYBOARD_COMMAND，如果是，则直接返回
        return;                                                 
    }
    User_Data[0] = USER_EMI_COMMAND;                            // 将 User_Data[0] 设置为 USER_EMI_COMMAND，修改数据的第一个字节以标识为 EMI 命令
    raw_hid_send(User_Data, 32);                                // 调用 raw_hid_send 函数发送 User_Data 数据，数据长度固定为32字节
}
/*********************************************************/

/************************eeprom**************************/
#if defined(EEPROM_CUSTOM)
/* Exported Constants --------------------------------------------------------*/
/* Define the size of the sectors to be used */
#define MCU_PAGE_SIZE           (uint32_t)0x200   /* MCU page size = 0.5kB */
#define PAGE_SIZE               (uint32_t)0x2000  /* Page size = 8kB */
#define MCU_PAGE_NUM            PAGE_SIZE / MCU_PAGE_SIZE

/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS  ((uint32_t)0x1C000)

/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS))
#define PAGE0_END_ADDRESS     ((uint32_t)(PAGE0_BASE_ADDRESS + (PAGE_SIZE - 1)))

#define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE))
#define PAGE1_END_ADDRESS     ((uint32_t)(PAGE1_BASE_ADDRESS + (PAGE_SIZE - 1)))

/* Used Flash pages for EEPROM emulation */
#define PAGE0                 ((uint32_t)0x00000000)
#define PAGE1                 ((uint32_t)0x00000001)

/* No valid page define */
#define NO_VALID_PAGE         ((uint32_t)0x000000AB)

/* Page status definitions */
#define ERASED                ((uint32_t)0xFFFFFFFF)     /* Page is empty */
#define RECEIVE_DATA          ((uint32_t)0xEEEEEEEE)     /* Page is marked to receive data */
#define VALID_PAGE            ((uint32_t)0x00000000)     /* Page containing valid data */

/* Valid pages in read and write defines */
#define READ_FROM_VALID_PAGE  ((uint8_t)0x00)
#define WRITE_IN_VALID_PAGE   ((uint8_t)0x01)

/* Page full define */
#define PAGE_FULL             ((uint8_t)0x80)

/* Variables' number */
#define NB_OF_VAR             (EEPROM_SIZE)
#define NB_OF_PRIVATE_VAR     (64)

#define ES_MCU_MEM_REMAP_OFFSET  ((((SYSCFG->REMAP)&SYSCFG_REMAP_REALBASE_MSK) >> SYSCFG_REMAP_REALBASE_POSS) << 12)

//__attribute__((aligned(4))) static uint8_t g_es_flash_eeprom_table[EEPROM_SIZE + 2];
__attribute__((aligned(4))) static uint8_t g_es_flash_eeprom_table[EEPROM_SIZE + NB_OF_PRIVATE_VAR + 2];

volatile uint32_t g_tst_remap_offset;

static uint32_t ee_format(void);
static uint32_t ee_find_valid_page(uint8_t operation);
static uint32_t ee_verify_pagefull_write_variable(uint32_t virt_address, uint32_t data);
static uint32_t ee_page_transfer(uint32_t virt_address, uint32_t data);

static uint32_t IAPROM_PAGE_ERASE(uint32_t addr)
{
    md_fc_ControlTypeDef SErasePara;

    if ((addr & 0x1ff) != 0)
    {
        return !SET;
    }

    __disable_irq();

        md_fc_unlock();

        SErasePara.SAddr = addr;
        SErasePara.SAddrC = ~(addr);

        md_fc_page_erase(&SErasePara);

        md_fc_lock();
    __enable_irq();

    return SET;
}

static uint32_t IAPROM_WORD_PROGRAM(uint32_t addr,uint32_t data)
{
    md_fc_ControlTypeDef ProgramPara;

    if ((addr & 0x3) != 0)
    {
        return !SET;
    }

    if ((((uint32_t)(&data)) & 0x3) != 0)
    {
        return !SET;
    }

    __disable_irq();

        md_fc_unlock();

        ProgramPara.BCnt = 4;
        ProgramPara.pU32Buf = &data;
        ProgramPara.SAddr = addr;
        ProgramPara.SAddrC = ~(addr);

        md_fc_program(&ProgramPara);

        md_fc_lock();
    __enable_irq();

    return SET;
}

static uint32_t ee_init(void)
{
    uint32_t page_status0 = 6U, page_status1 = 6U;
    uint32_t var_idx = 0U;
    uint32_t eeprom_status = 0U;
    uint32_t flash_status;
    uint8_t addr_index;
    uint32_t rom_read_end;

    /* Get Page0 status */
    page_status0 = (*(__IO uint32_t *)(PAGE0_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET));
    /* Get Page1 status */
    page_status1 = (*(__IO uint32_t *)(PAGE1_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET));

    if(page_status0 == VALID_PAGE)
    {
        rom_read_end = PAGE0_END_ADDRESS - ES_MCU_MEM_REMAP_OFFSET;
        for(var_idx = PAGE0_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET + 4;var_idx < rom_read_end;var_idx += 4)
        {
            if(((*(__IO uint32_t *)var_idx) >> 16) < NB_OF_VAR)
            {
                *(((uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + ((*(__IO uint32_t *)var_idx) >> 16)) = (*(__IO uint32_t *)var_idx) & 0xFFFF;
            }
            else
            {
                break;
            }
        }
    }

    if(page_status1 == VALID_PAGE)
    {
        rom_read_end = PAGE1_END_ADDRESS - ES_MCU_MEM_REMAP_OFFSET;
        for(var_idx = PAGE1_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET + 4;var_idx < rom_read_end;var_idx += 4)
        {
            if(((*(__IO uint32_t *)var_idx) >> 16) < NB_OF_VAR)
            {
                *(((uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + ((*(__IO uint32_t *)var_idx) >> 16)) = (*(__IO uint32_t *)var_idx) & 0xFFFF;
            }
            else
            {
                break;
            }
        }
    }

    /* Check for invalid header states and repair if necessary */
    switch (page_status0)
    {
        case ERASED:
            if (page_status1 == VALID_PAGE) /* Page0 erased, Page1 valid */
            {
                /* Erase Page0 */
                for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
                {
                    IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
                }
            }
            else if (page_status1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
            {
                /* Erase Page0 */
                for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
                {
                    IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
                }

                IAPROM_WORD_PROGRAM(PAGE1_BASE_ADDRESS, VALID_PAGE);
            }
            else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
            {
                /* Erase both Page0 and Page1 and set Page0 as valid page */
                flash_status = ee_format();

                if (flash_status != SET)
                    return flash_status;
            }

            break;

        case RECEIVE_DATA:
            if (page_status1 == VALID_PAGE) /* Page0 receive, Page1 valid */
            {
                /* Transfer data from Page1 to Page0 */
                for (var_idx = 0; var_idx < (NB_OF_VAR / 2 + 1); var_idx++)
                {
                    if((*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)) != 0)
                    {
                        /* Transfer the variable to the Page0 */
                            eeprom_status = ee_verify_pagefull_write_variable(var_idx, (*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)));

                            /* If program operation was failed, a Flash error code is returned */
                            if (eeprom_status != SET)
                                return eeprom_status;
                    }
                }

                IAPROM_WORD_PROGRAM(PAGE0_BASE_ADDRESS, VALID_PAGE);

                /* Erase Page1 */
                for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
                {
                    IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
                }
            }
            else if (page_status1 == ERASED) /* Page0 receive, Page1 erased */
            {
                /* Erase Page1 */
                for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
                {
                    IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
                }

                IAPROM_WORD_PROGRAM(PAGE0_BASE_ADDRESS, VALID_PAGE);
            }
            else /* Invalid state -> format eeprom */
            {
                flash_status = ee_format();
                if (flash_status != SET)
                    return flash_status;
            }

            break;

        case VALID_PAGE:
            if (page_status1 == VALID_PAGE) /* Invalid state -> format eeprom */
            {
                flash_status = ee_format();
                if (flash_status != SET)
                    return flash_status;
            }
            else if (page_status1 == ERASED) /* Page0 valid, Page1 erased */
            {
                for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
                {
                    IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
                }
            }
            else /* Page0 valid, Page1 receive */
            {
                /* Transfer data from Page0 to Page1 */
                for (var_idx = 0; var_idx < (NB_OF_VAR / 2 + 1); var_idx++)
                {
                    if((*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)) != 0)
                    {
                        /* Transfer the variable to the Page0 */
                            eeprom_status = ee_verify_pagefull_write_variable(var_idx, (*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)));

                            /* If program operation was failed, a Flash error code is returned */
                            if (eeprom_status != SET)
                                return eeprom_status;
                    }
                }

                IAPROM_WORD_PROGRAM(PAGE1_BASE_ADDRESS, VALID_PAGE);

                for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
                {
                    IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
                }
            }

            break;

        default:  /* Any other state -> format eeprom */
            flash_status = ee_format();
            if (flash_status != SET)
                return flash_status;

            break;
    }

    return SET;
}

static uint32_t ee_write_variable(uint32_t virt_address)
{
    uint32_t status = 0U;
    uint16_t data;

    if(virt_address >= NB_OF_VAR)
    {
        return !SET;
    }

    virt_address = virt_address / 2;

    data = *(((uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + virt_address);

    /* Write the variable virtual address and value in the EEPROM */
    status = ee_verify_pagefull_write_variable(virt_address, data);

    /* In case the EEPROM active page is full */
    if (status == PAGE_FULL)
        status = ee_page_transfer(virt_address, data);  /* Perform Page transfer */

    /* Return last operation status */
    return status;
}

static uint32_t ee_format(void)
{
    uint32_t flash_status = SET;
    uint8_t addr_index;

    /* Erase Page0 */
    for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
    {
        IAPROM_PAGE_ERASE(PAGE0_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
    }

    /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
    IAPROM_WORD_PROGRAM(PAGE0_BASE_ADDRESS, VALID_PAGE);

    /* Erase Page1 */
    for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
    {
        IAPROM_PAGE_ERASE(PAGE1_BASE_ADDRESS + addr_index * MCU_PAGE_SIZE);
    }

    /* Return Page1 erase operation status */
    return flash_status;
}

static uint32_t ee_find_valid_page(uint8_t operation)
{
    uint32_t page_status0 = 6U, page_status1 = 6U;

    /* Get Page0 status */
    page_status0 = (*(__IO uint32_t *)(PAGE0_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET));
    /* Get Page1 status */
    page_status1 = (*(__IO uint32_t *)(PAGE1_BASE_ADDRESS - ES_MCU_MEM_REMAP_OFFSET));

    /* Write or read operation */
    switch (operation)
    {
        case WRITE_IN_VALID_PAGE:   /* ---- Write operation ---- */
            if (page_status1 == VALID_PAGE)
            {
                /* Page0 receiving data */
                if (page_status0 == RECEIVE_DATA)
                    return PAGE0;         /* Page0 valid */
                else
                    return PAGE1;         /* Page1 valid */
            }
            else if (page_status0 == VALID_PAGE)
            {
                /* Page1 receiving data */
                if (page_status1 == RECEIVE_DATA)
                    return PAGE1;         /* Page1 valid */
                else
                    return PAGE0;         /* Page0 valid */
            }
            else
            {
                return NO_VALID_PAGE;   /* No valid Page */
            }

        case READ_FROM_VALID_PAGE:  /* ---- Read operation ---- */
            if (page_status0 == VALID_PAGE)
                return PAGE0;           /* Page0 valid */
            else if (page_status1 == VALID_PAGE)
                return PAGE1;           /* Page1 valid */
            else
                return NO_VALID_PAGE ;  /* No valid Page */

        default:
            return PAGE0;             /* Page0 valid */
    }
}

static uint32_t ee_verify_pagefull_write_variable(uint32_t virt_address, uint32_t data)
{
    uint32_t flash_status = SET;
    uint32_t valid_page = PAGE0;
    uint32_t address = EEPROM_START_ADDRESS;
    uint32_t page_endaddress = EEPROM_START_ADDRESS + PAGE_SIZE;

    /* Get valid Page for write operation */
    valid_page = ee_find_valid_page(WRITE_IN_VALID_PAGE);

    /* Check if there is no valid page */
    if (valid_page == NO_VALID_PAGE)
        return NO_VALID_PAGE;

    /* Get the valid Page start address */
    address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(valid_page * PAGE_SIZE)) - ES_MCU_MEM_REMAP_OFFSET;

    /* Get the valid Page end address */
    page_endaddress = (uint32_t)((EEPROM_START_ADDRESS - 4) + (uint32_t)((1 + valid_page) * PAGE_SIZE)) - ES_MCU_MEM_REMAP_OFFSET;

    /* Check each active page address starting from begining */
    while (address <= page_endaddress)
    {
        /* Verify if address and address+4 contents are 0xFFFFFFFF */
        if ((*(__IO uint32_t *)address) == 0xFFFFFFFF)
        {
            /* Set variable virtual address and data */
            flash_status = IAPROM_WORD_PROGRAM(address + ES_MCU_MEM_REMAP_OFFSET, (virt_address << 16) | data);
            /* Return program operation status */
            return flash_status;
        }
        else
        {
            /* Next address location */
            address = address + 4;
        }
    }

    /* Return PAGE_FULL in case the valid page is full */
    return PAGE_FULL;
}

static uint32_t ee_page_transfer(uint32_t virt_address, uint32_t data)
{
    uint32_t flash_status = SET;
    uint32_t new_pageaddress = EEPROM_START_ADDRESS;
    uint32_t old_pageaddress;
    uint32_t valid_page = PAGE0, var_idx = 0U;
    uint32_t eeprom_status = 0U;
    uint8_t addr_index;

    /* Get active Page for read operation */
    valid_page = ee_find_valid_page(READ_FROM_VALID_PAGE);

    if (valid_page == PAGE1)       /* Page1 valid */
    {
        /* New page address where variable will be moved to */
        new_pageaddress = PAGE0_BASE_ADDRESS;

        /* Old page ID where variable will be taken from */
        old_pageaddress = PAGE1_BASE_ADDRESS;
    }
    else if (valid_page == PAGE0)  /* Page0 valid */
    {
        /* New page address  where variable will be moved to */
        new_pageaddress = PAGE1_BASE_ADDRESS;

        /* Old page ID where variable will be taken from */
        old_pageaddress = PAGE0_BASE_ADDRESS;
    }
    else
    {
        return NO_VALID_PAGE;       /* No valid Page */
    }

    /* Erase the new Page*/
    for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
    {
        IAPROM_PAGE_ERASE(new_pageaddress + addr_index * MCU_PAGE_SIZE);
    }

    /* Set the new Page status to RECEIVE_DATA status */
    IAPROM_WORD_PROGRAM(new_pageaddress, RECEIVE_DATA);

    /* Write the variable passed as parameter in the new active page */
    eeprom_status = ee_verify_pagefull_write_variable(virt_address, data);

    /* If program operation was failed, a Flash error code is returned */
    if (eeprom_status != SET)
        return eeprom_status;

    /* Transfer process: transfer variables from old to the new active page */
    //for (var_idx = 0; var_idx < NB_OF_VAR; var_idx++)
    {
                /* Transfer data from Page1 to Page0 */
                for (var_idx = 0; var_idx < (NB_OF_VAR / 2 + 1); var_idx++)
                {
                    if((*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)) != 0)
                    {
                        /* Transfer the variable to the Page0 */
                            eeprom_status = ee_verify_pagefull_write_variable(var_idx, (*(((__IO uint16_t*)((uint32_t)g_es_flash_eeprom_table)) + var_idx)));

                            /* If program operation was failed, a Flash error code is returned */
                            if (eeprom_status != SET)
                                return eeprom_status;
                    }
                }
    }

    /* Erase the old Page: Set old Page status to ERASED status */
    for (addr_index = 0; addr_index < MCU_PAGE_NUM; addr_index++)
    {
        IAPROM_PAGE_ERASE(old_pageaddress + addr_index * MCU_PAGE_SIZE);
    }

    /* Set new Page status to VALID_PAGE status */
    IAPROM_WORD_PROGRAM(new_pageaddress, VALID_PAGE);

    /* Return last operation flash status */
    return flash_status;
}

size_t clamp_length(intptr_t offset, size_t len) {
    if (offset + len > EEPROM_SIZE) {
        len = EEPROM_SIZE - offset;
    }

    return len;
}

size_t clamp_length_user(intptr_t offset, size_t len) {
    if (offset + len > NB_OF_PRIVATE_VAR) {
        len = NB_OF_PRIVATE_VAR - offset;
    }

    return len;
}

void eeprom_driver_erase(void) {
    ee_format();
    memset(g_es_flash_eeprom_table, 0x00, sizeof(g_es_flash_eeprom_table));
}

#define USER_EEPROM_START_ADDRESS1  (EEPROM_START_ADDRESS - (MCU_PAGE_SIZE))
volatile uint8_t es_eeprom_init_flag = 0U;

void eeprom_driver_init(void) {
    if(es_eeprom_init_flag)
        return;

    g_tst_remap_offset = ES_MCU_MEM_REMAP_OFFSET;
    (void)g_tst_remap_offset;
    memset(g_es_flash_eeprom_table, 0x00, sizeof(g_es_flash_eeprom_table));
    ee_init();
    memcpy(g_es_flash_eeprom_table, (uint8_t*)(USER_EEPROM_START_ADDRESS1 - ES_MCU_MEM_REMAP_OFFSET), NB_OF_PRIVATE_VAR);
    es_eeprom_init_flag = 1;
}
/*****************eeprom块读取********************/
void eeprom_read_block(void *buf, const void *addr, size_t len) {

    intptr_t offset = (intptr_t)addr;
    memset(buf, 0x00, len);//将buf地址里面的len长度字节全部初始化为0x00
    len = clamp_length(offset, len);
    if (len > 0) {
        memcpy(buf, &g_es_flash_eeprom_table[NB_OF_PRIVATE_VAR + offset], len);
    }
}
/*****************eeprom块写入********************/
void eeprom_write_block(const void *buf, void *addr, size_t len) {
    uint16_t i;
    intptr_t offset = (intptr_t)addr;
                len = clamp_length(offset, len);
    if (len > 0) {
        for(i = 0;i < len;i++)
        {
            if(g_es_flash_eeprom_table[i + offset + NB_OF_PRIVATE_VAR] != (*((uint8_t*)((uint32_t)buf) + i)))
            {
                g_es_flash_eeprom_table[i + offset + NB_OF_PRIVATE_VAR] = (*((uint8_t*)((uint32_t)buf) + i));
                ee_write_variable(i + offset + NB_OF_PRIVATE_VAR);

            }
        }

        memcpy(&g_es_flash_eeprom_table[offset + NB_OF_PRIVATE_VAR], buf, len);
    }
}

void eeprom_read_block_user(void *buf, const void *addr, size_t len) {
    intptr_t offset = (intptr_t)addr;
    memset(buf, 0x00, len);
    len = clamp_length_user(offset, len);
    if (len > 0) {
        memcpy(buf, (uint8_t*)(USER_EEPROM_START_ADDRESS1 - ES_MCU_MEM_REMAP_OFFSET) + offset, len);
    }
}

void eeprom_write_block_user(const void *buf, void *addr, size_t len) {
    md_fc_ControlTypeDef ProgramPara;
    intptr_t offset = (intptr_t)addr;
    len             = clamp_length_user(offset, len);
    if (len > 0) {
        __disable_irq();
            if(memcmp(buf,(uint8_t*)(USER_EEPROM_START_ADDRESS1 - ES_MCU_MEM_REMAP_OFFSET) + offset,len))
            {
                    memcpy(&g_es_flash_eeprom_table[offset], buf, len);

                    md_fc_unlock();
                    ProgramPara.SAddr = USER_EEPROM_START_ADDRESS1;
                    ProgramPara.SAddrC = ~(USER_EEPROM_START_ADDRESS1);
                    md_fc_page_erase(&ProgramPara);
                    md_fc_lock();

                    md_fc_unlock();
                    ProgramPara.BCnt = NB_OF_PRIVATE_VAR;
                    ProgramPara.pU32Buf = (uint32_t*)(&g_es_flash_eeprom_table);
                    ProgramPara.SAddr = USER_EEPROM_START_ADDRESS1;
                    ProgramPara.SAddrC = ~(USER_EEPROM_START_ADDRESS1);
                    md_fc_program(&ProgramPara);
                    md_fc_lock();
            }
        __enable_irq();
    }
}
#endif
/*********************************************************/

/************************ENCODER**************************/
#ifdef ENCODER_ENABLE

#if !defined(ENCODER_RESOLUTIONS) && !defined(ENCODER_RESOLUTION)
#    define ENCODER_RESOLUTION 1
#endif

#undef ENCODER_DEFAULT_PIN_API_IMPL
#if defined(ENCODERS_PAD_A) && defined(ENCODERS_PAD_B)
// Inform the quadrature driver that it needs to implement pin init/read functions
#    define ENCODER_DEFAULT_PIN_API_IMPL
#endif

extern volatile bool isLeftHand;

__attribute__((weak)) void    encoder_quadrature_init_pin(uint8_t index, bool pad_b);
__attribute__((weak)) uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b);

#ifdef ENCODER_DEFAULT_PIN_API_IMPL

static pin_t encoders_pad_a[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_A;
static pin_t encoders_pad_b[NUM_ENCODERS_MAX_PER_SIDE] = ENCODERS_PAD_B;

__attribute__((weak)) void encoder_wait_pullup_charge(void) {
    wait_us(100);
}

__attribute__((weak)) void encoder_quadrature_init_pin(uint8_t index, bool pad_b) {
    pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
    if (pin != NO_PIN) {
        gpio_set_pin_input_high(pin);
    }
}

__attribute__((weak)) uint8_t encoder_quadrature_read_pin(uint8_t index, bool pad_b) {
    pin_t pin = pad_b ? encoders_pad_b[index] : encoders_pad_a[index];
    if (pin != NO_PIN) {
        return gpio_read_pin(pin) ? 1 : 0;
    }
    return 0;
}

#endif // ENCODER_DEFAULT_PIN_API_IMPL

#ifdef ENCODER_RESOLUTIONS
static uint8_t encoder_resolutions[NUM_ENCODERS] = ENCODER_RESOLUTIONS;
#endif

#ifndef ENCODER_DIRECTION_FLIP
#    define ENCODER_CLOCKWISE true
#    define ENCODER_COUNTER_CLOCKWISE false
#else
#    define ENCODER_CLOCKWISE false
#    define ENCODER_COUNTER_CLOCKWISE true
#endif
static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};

static uint8_t encoder_state[NUM_ENCODERS]  = {0};
static int8_t  encoder_pulses[NUM_ENCODERS] = {0};

// encoder counts
static uint8_t thisCount;

__attribute__((weak)) void encoder_quadrature_post_init_kb(void) {
    extern void encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state);
    // Unused normally, but can be used for things like setting up pin-change interrupts in keyboard code.
    // During the interrupt, read the pins then call `encoder_handle_read()` with the pin states and it'll queue up an encoder event if needed.
}

void encoder_quadrature_post_init(void) {
#ifdef ENCODER_DEFAULT_PIN_API_IMPL
    for (uint8_t i = 0; i < thisCount; i++) {
        encoder_quadrature_init_pin(i, false);
        encoder_quadrature_init_pin(i, true);
    }
    encoder_wait_pullup_charge();
    for (uint8_t i = 0; i < thisCount; i++) {
        encoder_state[i] = (encoder_quadrature_read_pin(i, false) << 0) | (encoder_quadrature_read_pin(i, true) << 1);
    }
#else
    memset(encoder_state, 0, sizeof(encoder_state));
#endif

    encoder_quadrature_post_init_kb();
}

void encoder_driver_init(void) {
    thisCount                = NUM_ENCODERS;

#ifdef ENCODER_TESTS
    // Annoying that we have to clear out values during initialisation here, but
    // because all the arrays are static locals, rerunning tests in the same
    // executable doesn't reset any of these. Kinda crappy having test-only code
    // here, but it's the simplest solution.
    memset(encoder_state, 0, sizeof(encoder_state));
    memset(encoder_pulses, 0, sizeof(encoder_pulses));
    const pin_t encoders_pad_a_left[] = ENCODERS_PAD_A;
    const pin_t encoders_pad_b_left[] = ENCODERS_PAD_B;
    for (uint8_t i = 0; i < thisCount; i++) {
        encoders_pad_a[i] = encoders_pad_a_left[i];
        encoders_pad_b[i] = encoders_pad_b_left[i];
    }
#endif

    encoder_quadrature_post_init();
}

static void encoder_handle_state_change(uint8_t index, uint8_t state) {
    uint8_t i = index;

#ifdef ENCODER_RESOLUTIONS
    const uint8_t resolution = encoder_resolutions[index];
#else
    const uint8_t resolution = ENCODER_RESOLUTION;
#endif

    encoder_pulses[i] += encoder_LUT[state & 0xF];

#ifdef ENCODER_DEFAULT_POS
    if ((encoder_pulses[i] >= resolution) || (encoder_pulses[i] <= -resolution) || ((state & 0x3) == ENCODER_DEFAULT_POS)) {
        if (encoder_pulses[i] >= 1) {
#else
    if (encoder_pulses[i] >= resolution) {
#endif

            encoder_queue_event(index, ENCODER_COUNTER_CLOCKWISE);
        }

#ifdef ENCODER_DEFAULT_POS
        if (encoder_pulses[i] <= -1) {
#else
    if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
#endif
            encoder_queue_event(index, ENCODER_CLOCKWISE);
        }
        encoder_pulses[i] %= resolution;
#ifdef ENCODER_DEFAULT_POS
        encoder_pulses[i] = 0;
    }
#endif
}

void encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state) {
    uint8_t state = pin_a_state | (pin_b_state << 1);
    if ((encoder_state[index] & 0x3) != state) {
        encoder_state[index] <<= 2;
        encoder_state[index] |= state;
        encoder_handle_state_change(index, encoder_state[index]);
    }
}

__attribute__((weak)) void encoder_driver_task(void) {
    for (uint8_t i = 0; i < thisCount; i++) {
        encoder_quadrature_handle_read(i, encoder_quadrature_read_pin(i, false), encoder_quadrature_read_pin(i, true));
    }
}
#endif
/*********************************************************/

uint8_t es_keyboard_leds(void) {
    switch (Keyboard_Info.Key_Mode) {
        case QMK_2P4G_MODE: break;
        case QMK_BLE_MODE:  break;
        case QMK_USB_MODE:  break;
        default:            break;
    }

    //原接口调用
    if(es_qmk_driver)
        return((*es_qmk_driver->keyboard_leds)());

    return 0;
}

/*发送6键类型数据*/
void    es_send_keyboard(report_keyboard_t *report) {
    switch (Keyboard_Info.Key_Mode) {
        case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_keyboard_t));  break;
        case QMK_BLE_MODE:  User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_keyboard_t));  break;
        case QMK_USB_MODE:  break;
        default:            break;
    }

    //原接口调用
    if(es_qmk_driver)
        (*es_qmk_driver->send_keyboard)(report);
}

/*发送全键类型数据*/
void    es_send_nkro(report_nkro_t *report) {
    switch (Keyboard_Info.Key_Mode) {
        case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_nkro_t));  break;
        case QMK_BLE_MODE:  User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_nkro_t));  break;
        case QMK_USB_MODE:  break;
        default:            break;
    }

    //原接口调用
    if(es_qmk_driver)
        (*es_qmk_driver->send_nkro)(report);
}

/*发送鼠标类型数据*/
void    es_send_mouse(report_mouse_t *report) {
    switch (Keyboard_Info.Key_Mode) {
        case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_mouse_t));  break;
        case QMK_BLE_MODE:  User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_mouse_t));  break;
        case QMK_USB_MODE:  break;
        default:            break;
    }

    //原接口调用
    if(es_qmk_driver)
        (*es_qmk_driver->send_mouse)(report);
}

/*发送多媒体类型数据*/
void    es_send_extra(report_extra_t *report) {
    switch (Keyboard_Info.Key_Mode) {
        case QMK_2P4G_MODE: User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_extra_t));  break;
        case QMK_BLE_MODE:  User_bluetooth_send_keyboard((uint8_t *)report,sizeof(report_extra_t));  break;
        case QMK_USB_MODE:  break;
        default:            break;
    }

    //原接口调用
    if(es_qmk_driver)
        (*es_qmk_driver->send_extra)(report);
}

/*系统复位*/
void es_mcu_reset(void) {
    uint16_t Time_Delay = 0;
    /*如果spi正在繁忙，则等待100us左右的时间，如果超时则直接返回*/
    while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || Reset_Save_Flash){
        Time_Delay++;
        if (Time_Delay >= 36000) {
            Time_Delay = 0;
            break;
        }
    }
    gpio_write_pin_low(ES_LED_POWER_IO);

    NVIC_SystemReset();
}

/*跳转boot*/
void bootloader_jump(void) {
    uint16_t Time_Delay = 0;
    /*如果spi正在繁忙，则等待100us左右的时间，如果超时则直接返回*/
    while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || Reset_Save_Flash){
        Time_Delay++;
        if (Time_Delay >= 36000) {
            Time_Delay = 0;
            break;
        }
    }

    gpio_write_pin_low(ES_LED_POWER_IO);

    /*Remap EFLASH,remap to boot*/
    md_fc_lock();
    md_syscfg_set_memory_mapping(SYSCFG, MD_SYSCFG_MEMMOD_MAIN);
    md_syscfg_set_flash_remap_base(SYSCFG, 0);
    md_syscfg_enable_memory_remap(SYSCFG);
    NVIC_SystemReset();
}

/*MCU复位*/
void mcu_reset(void) {
    uint16_t Time_Delay = 0;
    /*如果spi正在繁忙，则等待100us左右的时间，如果超时则直接返回*/
    while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || Reset_Save_Flash){
        Time_Delay++;
        if (Time_Delay >= 36000) {
            Time_Delay = 0;
            break;
        }
    }

    gpio_write_pin_low(ES_LED_POWER_IO);

    NVIC_SystemReset();
}

/*写入flash*/
void Save_Flash_Set(void) {
    Save_Flash = true;
    Save_Flash_3S_Count = 0;
}

/************************SPI*****************************/
const uint32_t g_es_dma_ch2pri_cfg = ((MD_DMA_CHANNEL_CFG_MODE_PERIPHERAL_PRIMARY) | \
                                   ((MD_DMA_CHANNEL_CFG_RPOWER_SIZE_4) << 14) | \
                                   ((MD_DMA_CHANNEL_CFG_SRCDATA_SIZE_WORD) << 24) | \
                                   ((MD_DMA_CHANNEL_CFG_SRCINC_WORD) << 26) | \
                                   ((MD_DMA_CHANNEL_CFG_DSTDATA_SIZE_WORD) << 28) | \
                                   ((MD_DMA_CHANNEL_CFG_DSTINC_WORD) << 30));

const uint32_t g_es_dma_ch2alt_cfg = ((MD_DMA_CHANNEL_CFG_MODE_PERIPHERAL_ALTERNATE) | \
                                   ((MD_DMA_CHANNEL_CFG_RPOWER_SIZE_1) << 14) | \
                                   ((MD_DMA_CHANNEL_CFG_SRCDATA_SIZE_BYTE) << 24) | \
                                   ((MD_DMA_CHANNEL_CFG_SRCINC_BYTE) << 26) | \
                                   ((MD_DMA_CHANNEL_CFG_DSTDATA_SIZE_BYTE) << 28) | \
                                   ((MD_DMA_CHANNEL_CFG_DSTINC_NO_INC) << 30));

const md_spi_inittypedef SPI2_InitStruct =    /**< SPI init structure */
{
    MD_SPI_MODE_MASTER,                //主机
    MD_SPI_PHASE_2EDGE,                //第二个时钟转换是第一个数据捕获边缘 上升沿
    MD_SPI_POLARITY_HIGH,              //为高空闲 低电平有效
    MD_SPI_BAUDRATEPRESCALER_DIV8,     //48/8 = 6M
    MD_SPI_MSB_FIRST,                  //高位先出
    MD_SPI_FULL_DUPLEX,                //全双工模式
    MD_SPI_FRAME_FORMAT_8BIT,          //8位数据格式
    MD_SPI_NSS_HARD,                   //硬件控制CS脚
};

void es_ble_spi_init(void)
{
    md_gpio_inittypedef gpiox;

    md_rcu_enable_spi2(RCU);

    gpiox.Pin   = MD_GPIO_PIN_0;
    gpiox.Mode  = MD_GPIO_MODE_FUNCTION;
    gpiox.OutputType = MD_GPIO_OUTPUT_PUSHPULL;
    gpiox.Pull  = MD_GPIO_PULL_UP;
    gpiox.OutDrive = MD_GPIO_DRIVING_8MA;
    gpiox.Function = MD_GPIO_AF0;
    md_gpio_init(GPIOC, &gpiox);

    gpiox.Pin   = MD_GPIO_PIN_1;
    md_gpio_init(GPIOC, &gpiox);

    gpiox.Pin   = MD_GPIO_PIN_2;
    md_gpio_init(GPIOC, &gpiox);

    gpiox.Pin   = MD_GPIO_PIN_3;
    md_gpio_init(GPIOC, &gpiox);

    md_spi_init(SPI2, (md_spi_inittypedef *)(&SPI2_InitStruct));
}

void es_ble_spi_deinit(void) {

    md_rcu_enable_spi2_reset(RCU);
    md_rcu_disable_spi2_reset(RCU);
    md_rcu_disable_spi2(RCU);

    /*PC0 PC1 PC2 PC3回到复位值*/
    GPIOC->MOD |= 0x000000FF;
    GPIOC->PUD &= 0xFFFFFF00;
    GPIOC->OT  &= 0xFFFFFF00;
    GPIOC->DS  &= 0xFFFFFF00;
    GPIOC->IST &= 0xFFFFFF00;
}

void es_spi_send_recv_by_dma(uint32_t num, uint8_t *rx_buf, uint8_t *tx_buf)
{
	uint32_t tx_index = 0;
	uint32_t rx_index = 0;

    __disable_irq();

	if(((uint32_t)tx_buf) >= 0x20000000) {
		if(num & 0x1) {
			SPI2->DATA = tx_buf[tx_index++];
		}

		while(tx_index < num) {
			if(md_spi_get_txfifo_value(SPI2) <= 2) {
				SPI2->DATA = tx_buf[tx_index++];
				SPI2->DATA = tx_buf[tx_index++];
			}

			if(md_spi_get_rxfifo_value(SPI2)) {
				rx_buf[rx_index++] = SPI2->DATA;
			}
		}

		while(rx_index < num) {
			if(md_spi_get_rxfifo_value(SPI2)) {
				rx_buf[rx_index++] = SPI2->DATA;
			}
		}
	} else {
		if(num & 0x1) {
			SPI2->DATA = 0X00;
		}

		while(tx_index < num) {
			if(md_spi_get_txfifo_value(SPI2) <= 2) {
				SPI2->DATA = 0X00;
				SPI2->DATA = 0X00;
				tx_index += 2;
			}

			if(md_spi_get_rxfifo_value(SPI2)) {
				rx_buf[rx_index++] = SPI2->DATA;
			}
		}

		while(rx_index < num) {
			if(md_spi_get_rxfifo_value(SPI2)) {
				rx_buf[rx_index++] = SPI2->DATA;
			}
		}
	}

    __enable_irq();
}

/*SPI发送命令函数*/
void Spi_Send_Commad(uint8_t Commad) {
    if (Init_Spi_Power_Up || Keyboard_Status.System_Work_Status) {
        return;
    }

    uint16_t Time_Delay = 0;
    /*如果spi正在繁忙，则等待100us左右的时间，如果超时则直接返回*/
    while (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO))){
        Time_Delay++;
        if (Time_Delay >= 2000) {
            Time_Delay = 0;
            return;
        }
    }

    Spi_Send_Recv_Flg = 1;
    Send_Key_Type = SPI_NACK;
    Spi_Interval = SPI_DELAY_RF_TIME;

    /*将需要发送的指令发送到680*/
    g_es_spi_tx_buf[0] = USER_KEYBOARD_COMMAND;
    g_es_spi_tx_buf[1] = USER_KEYBOARD_LENGTH;
    g_es_spi_tx_buf[2] = Commad;
    if (Commad == USER_BATTERY_DATA) {
        g_es_spi_tx_buf[3] = Keyboard_Info.Batt_Number;
    } else if (Commad == USER_BLE1_WRITE_NAME) {
        g_es_spi_tx_buf[3] = ((USER_BlE_ID >> 8) & 0XFF);
        g_es_spi_tx_buf[4] = (USER_BlE_ID & 0X00FF);
        g_es_spi_tx_buf[5] = strlen(USER_BlE1_NAME);
        for (uint8_t len = 0; len < strlen(USER_BlE1_NAME); len++) {
            g_es_spi_tx_buf[6 + len] = USER_BlE1_NAME[len];
        }
    } else if (Commad == USER_BLE2_WRITE_NAME) {
        g_es_spi_tx_buf[3] = ((USER_BlE_ID >> 8) & 0XFF);
        g_es_spi_tx_buf[4] = (USER_BlE_ID & 0X00FF);
        g_es_spi_tx_buf[5] = strlen(USER_BlE2_NAME);
        for (uint8_t len = 0; len < strlen(USER_BlE2_NAME); len++) {
            g_es_spi_tx_buf[6 + len] = USER_BlE2_NAME[len];
        }
    } else if (Commad == USER_BLE3_WRITE_NAME) {
        g_es_spi_tx_buf[3] = ((USER_BlE_ID >> 8) & 0XFF);
        g_es_spi_tx_buf[4] = (USER_BlE_ID & 0X00FF);
        g_es_spi_tx_buf[5] = strlen(USER_BlE3_NAME);
        for (uint8_t len = 0; len < strlen(USER_BlE3_NAME); len++) {
            g_es_spi_tx_buf[6 + len] = USER_BlE3_NAME[len];
        }
    }

    es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf);
}

/*SPI发送命令函数*/
uint8_t Spi_Ack_Send_Commad(uint8_t Commad) {
    if (Init_Spi_Power_Up) {
        return SPI_BUSY;
    }

    if (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO))) {
        return SPI_BUSY;
    }

    Spi_Send_Recv_Flg = 1;
    Send_Key_Type = SPI_ACK;
    Repet_Send_Count = 0;

    /*将需要发送的指令发送到680*/
    g_es_spi_tx_buf[0] = USER_KEYBOARD_COMMAND;
    g_es_spi_tx_buf[1] = USER_KEYBOARD_LENGTH;
    g_es_spi_tx_buf[2] = Commad;
    es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf);
    return SPI_IDLE;
}

/*获取SPI数据函数*/
void Get_Spi_Return_Data(uint8_t *Data) {
    if (Emi_Test_Start) {
        Emi_Write_Data(Data, USER_KEYBOARD_LENGTH);
    } else {
        if (Data[2] == USER_GET_RF_STATUS) {
            Keyboard_Status.System_Work_Status = Data[3];   //休眠
            if (Keyboard_Status.System_Work_Status) {
                if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {
                    if (Usb_Change_Mode_Wakeup) {           //在无线工作模式下有按键按下3S内不会进休眠
                        User_Sleep();
                    } else {
                        Keyboard_Status.System_Work_Status = 0;
                    }
                } else {
                    Keyboard_Status.System_Work_Status = 0;
                    Spi_Interval = SPI_DELAY_USB_TIME;
                }
            }

            Keyboard_Status.System_Work_Mode = Data[4];     //工作模式
            if (Keyboard_Info.Key_Mode != Keyboard_Status.System_Work_Mode) {   //如果工作模式不同
                Mode_Synchronization_Signal = true;
                if (Keyboard_Status.System_Work_Status) {   //当680想进入休眠，模式不对则取消休眠，先切换模式
                    Keyboard_Status.System_Work_Status = 0;
                }
            } else {
                if (Keyboard_Info.Key_Mode == QMK_USB_MODE) {
                    Spi_Interval = SPI_DELAY_USB_TIME;
                }
            }

            Keyboard_Status.System_Work_Channel = Data[5];  //蓝牙通道
            if ((Keyboard_Info.Ble_Channel != Keyboard_Status.System_Work_Channel) && (Keyboard_Info.Key_Mode == QMK_BLE_MODE)) { //如果蓝牙通道不对
                Mode_Synchronization_Signal = true;
                if (Keyboard_Status.System_Work_Status) {   //当680想进入休眠，模式不对则取消休眠，先切换模式
                    Keyboard_Status.System_Work_Status = 0;
                }
            }

            Keyboard_Status.System_Connect_Status = Data[6];//连接状态
            if (Temp_System_Led_Status != Keyboard_Status.System_Connect_Status) {
                Temp_System_Led_Status = Keyboard_Status.System_Connect_Status;
                if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {
                    Led_Rf_Pair_Flg = true;
                } else {
                    Led_Rf_Pair_Flg = false;
                }
            }

            Keyboard_Status.System_Led_Status = Data[7];    //系统指示灯

            uint16_t Ble_ID = ((Data[8] << 8) | (Data[9]));
            if (Ble_ID != USER_BlE_ID) {                    //蓝牙ID获取
                if (Ble_Name_Spi_Send == false) {           //防止多次写名字
                    Ble_Name_Spi_Send = true;
                    Ble_Name_Spi_Count = QMK_BLE_CHANNEL_1;
                }
            }
        } else if (Data[2] == USER_KEYBOARD_SLEEP) {
            if (Keyboard_Status.System_Work_Status && (Data[3] == USER_SLEEP_PASS)) {       //系统休眠 停止一切活动，并且使能唤醒源
                if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {
                    Keyboard_Status.System_Sleep_Mode = 1;
                } else {
                    Keyboard_Status.System_Sleep_Mode = 0;
                }
            } else if (Data[3] == USER_SLEEP_FIAL) {
                Keyboard_Status.System_Work_Status = 0;
                Keyboard_Status.System_Sleep_Mode = 0;
            }
        }

        if (0XBB == Data[10]) {                             //进入EMI
            Emi_Test_Start = true;
            Emi_Init();
        }
    }
}
/*********************************************************/
/************************灯光*****************************/
#define ES_PWM_LED_SIZE         (42)
#define ES_PWM_LED_BYTE         (24)
#define ES_PWM_DMA_SIZE         (ES_PWM_LED_SIZE * ES_PWM_LED_BYTE)

#define ES_PWM_WS2812_H_VALUE   (43)
#define ES_PWM_WS2812_L_VALUE   (17)

rgb_led_t rgb_matrix_ws2812_array[RGB_MATRIX_LED_COUNT];
uint8_t g_es_pwm_rgb_matrix_array_dma_buf[(RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 2] = {0};
md_dma_channel_config_typedef DMA_list[5] = {0};
/*****************rgb矩阵驱动初始化********************/
static void rgb_matrix_driver_init(void)
{
    md_rcu_enable_dma1(RCU);//使能同步机制
    md_dma_set_configuration(DMA1, ENABLE);

    md_rcu_enable_gp16c2t1(RCU);
    md_timer_set_auto_reload_value_arrv(GP16C2T1, 60);//配置定时器C型GP16C2T1自动重装载
    md_timer_set_output_compare1_mode_ch1mod(GP16C2T1, MD_TIMER_OUTPUTMODE_PWMMODE1);//配置输出比较模式
    md_timer_set_capture_compare1_value_ccrv1(GP16C2T1, 0);//设置输入捕获寄存器值
    md_timer_enable_cc1_output_cc1en(GP16C2T1);//使能捕获计数器 ,md_timer_enable_main_output_goen(GP16C2T1);//使能死区和刹车寄存器
    md_timer_enable_main_output_goen(GP16C2T1);

    md_timer_enable_output_compare1_preload_ch1pen(GP16C2T1);//使能定时器预装载
    md_timer_enable_dma_upd(GP16C2T1);
    md_timer_enable_counter_cnten(GP16C2T1);

    gpio_set_pin_output(ES_PWM_DMA_IO);

    /*复用为PWM DMA方式*/
    GPIOA->AFL &= 0xFFFFF0FF;
    GPIOA->AFL |= 0x00000500;

    GPIOA->MOD &= 0xFFFFFFCF;
    GPIOA->MOD |= 0x00000020;

    md_dma_set_request_peripherals(DMA1, MD_DMA_CHANNEL2, MD_DMA_PRS_GP16C2T1_UP);

    if (rgb_matrix_get_val() <= 0) {                //优化背光速度调节到最低的时候，休眠唤醒灯光不亮问题
        memset((void *)g_es_pwm_rgb_matrix_array_dma_buf, ES_PWM_WS2812_L_VALUE, (RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 2);
    }
}

void User_Pwm_Deinit(void) {
    md_rcu_enable_gp16c2t1_reset(RCU);
    md_rcu_disable_gp16c2t1_reset(RCU);
    md_rcu_disable_gp16c2t1(RCU);
    md_rcu_enable_dma1_reset(RCU);
    md_rcu_disable_dma1_reset(RCU);
    md_rcu_disable_dma1(RCU);

    gpio_set_pin_output(ES_PWM_DMA_IO);
    gpio_write_pin_low(ES_PWM_DMA_IO);
}

static void rgb_matrix_driver_flush_pwm_dma_start(void)
{
    while ((DMA1->CHENSET) & 0x4);

    if (Keyboard_Status.System_Sleep_Mode || ((Keyboard_Info.Key_Mode != QMK_USB_MODE) && Usb_Change_Mode_Wakeup && Keyboard_Status.System_Work_Status) || (!Led_Power_Up)) {
        Led_Off_Start = true;
        gpio_write_pin_low(ES_LED_POWER_IO);
        return;
    }

    if (rgblight_is_enabled() && (Led_Point_Sleep == false)) {
        gpio_write_pin_high(ES_LED_POWER_IO);
        if (Led_Off_Start) {
            Led_Off_Start = false;
            wait_ms(3);
        }
    } else {                            //LED灯光休眠，停止向LED灯供电
        Led_Off_Start = true;
        gpio_write_pin_low(ES_LED_POWER_IO);
    }

    md_timer_disable_dma_upd(GP16C2T1);

    /*将buff的最后两个字节赋值为0*/
    g_es_pwm_rgb_matrix_array_dma_buf[(RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE)] = 0;
    g_es_pwm_rgb_matrix_array_dma_buf[(RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 1] = 0;

    #if (RGB_MATRIX_LED_COUNT <= 42)
        uint16_t Data_Size = ((RGB_MATRIX_LED_COUNT * ES_PWM_LED_BYTE) + 2);
        DMA_list[0].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + (Data_Size - 1));
        DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((16 - 4));
        DMA1->PRI_CH02_CHANNEL_CFG = ((4 - 1) << 4) | g_es_dma_ch2pri_cfg;
    #elif (RGB_MATRIX_LED_COUNT <= 84)
        DMA_list[0].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + (ES_PWM_DMA_SIZE - 1));
        DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        uint16_t Data_Size = (((RGB_MATRIX_LED_COUNT - ES_PWM_LED_SIZE) * ES_PWM_LED_BYTE) + 2);
        DMA_list[1].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[1].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + (ES_PWM_DMA_SIZE + Data_Size - 1));
        DMA_list[1].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((32 - 4));
        DMA1->PRI_CH02_CHANNEL_CFG = ((8 - 1) << 4) | g_es_dma_ch2pri_cfg;
    #elif (RGB_MATRIX_LED_COUNT <= 126)
        DMA_list[0].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + (ES_PWM_DMA_SIZE - 1));
        DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA_list[1].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[1].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + ((ES_PWM_DMA_SIZE * 2) - 1));
        DMA_list[1].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        uint16_t Data_Size = (((RGB_MATRIX_LED_COUNT - (ES_PWM_LED_SIZE * 2)) * ES_PWM_LED_BYTE) + 2);
        DMA_list[2].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[2].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf + ((ES_PWM_DMA_SIZE * 2) + Data_Size - 1));
        DMA_list[2].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((48 - 4));
        DMA1->PRI_CH02_CHANNEL_CFG = ((12 - 1) << 4) | g_es_dma_ch2pri_cfg;
    #elif (RGB_MATRIX_LED_COUNT <= 168)
        DMA_list[0].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[0].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + (ES_PWM_DMA_SIZE - 1));
        DMA_list[0].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA_list[1].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[1].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + ((ES_PWM_DMA_SIZE * 2) - 1));
        DMA_list[1].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA_list[2].control.word = ((ES_PWM_DMA_SIZE - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[2].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + ((ES_PWM_DMA_SIZE * 3) - 1));
        DMA_list[2].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        uint16_t Data_Size = (((RGB_MATRIX_LED_COUNT - (ES_PWM_LED_SIZE * 3)) * ES_PWM_LED_BYTE) + 2);
        DMA_list[3].control.word = ((Data_Size - 1) << 4) | g_es_dma_ch2alt_cfg;
        DMA_list[3].source_data_end_address = (uint32_t)(g_es_pwm_rgb_matrix_array_dma_buf  + ((ES_PWM_DMA_SIZE * 3) + Data_Size - 1));
        DMA_list[3].destination_data_end_address = (uint32_t)(&(GP16C2T1->CCVAL1));

        DMA1->PRI_CH02_SRC_DATA_END_PTR = ((uint32_t)(DMA_list)) + ((64 - 4));
        DMA1->PRI_CH02_CHANNEL_CFG = ((16 - 1) << 4) | g_es_dma_ch2pri_cfg;
    #endif

    DMA1->PRI_CH02_DST_DATA_END_PTR = ((uint32_t)(&(DMA1->ALT_CH02_SRC_DATA_END_PTR))) + 16 - 4;
    DMA1->CHENSET = 0x4;
    md_timer_enable_dma_upd(GP16C2T1);
}

static void rgb_matrix_driver_flush(void)
{
    Led_Flash_Busy = false;
    if((GP16C2T1->AR) != 60)
    {
        rgb_matrix_driver_init();
    }

    rgb_matrix_driver_flush_pwm_dma_start();
}

static void rgb_matrix_driver_set_color(int index, uint8_t r, uint8_t g, uint8_t b)
{
    uint8_t * buf;

    if (index == (RGB_MATRIX_LED_COUNT - 1)) {
        Led_Flash_Busy = false;
    } else if(index == 0){
        Led_Flash_Busy = true;
    }

    if (rgb_matrix_ws2812_array[index].r == r && rgb_matrix_ws2812_array[index].g == g && rgb_matrix_ws2812_array[index].b == b) {
        return;
    }

    rgb_matrix_ws2812_array[index].r = r;
    rgb_matrix_ws2812_array[index].g = g;
    rgb_matrix_ws2812_array[index].b = b;

    buf = g_es_pwm_rgb_matrix_array_dma_buf + (index * 24);

    for (unsigned char bit = 0; bit < 8; bit++) {
        bool is_one = g & (1 << (7 - bit));
        // using something like wait_ns(is_one ? T1L : T0L) here throws off timings

        *buf = (is_one)? ES_PWM_WS2812_H_VALUE : ES_PWM_WS2812_L_VALUE;
        buf++;
    }

    for (unsigned char bit = 0; bit < 8; bit++) {
        bool is_one = r & (1 << (7 - bit));
        // using something like wait_ns(is_one ? T1L : T0L) here throws off timings

        *buf = (is_one)? ES_PWM_WS2812_H_VALUE : ES_PWM_WS2812_L_VALUE;
        buf++;
    }

    for (unsigned char bit = 0; bit < 8; bit++) {
        bool is_one = b & (1 << (7 - bit));
        // using something like wait_ns(is_one ? T1L : T0L) here throws off timings

        *buf = (is_one)? ES_PWM_WS2812_H_VALUE : ES_PWM_WS2812_L_VALUE;
        buf++;
    }
}

static void rgb_matrix_driver_set_color_all(uint8_t r, uint8_t g, uint8_t b)
{
    for(uint32_t i = 0;i < RGB_MATRIX_LED_COUNT;i++) {
        rgb_matrix_driver_set_color(i,r,g,b);
    }
}

// clang-format off
const rgb_matrix_driver_t rgb_matrix_driver = {
    .init          = rgb_matrix_driver_init,
    .flush         = rgb_matrix_driver_flush,
    .set_color     = rgb_matrix_driver_set_color,
    .set_color_all = rgb_matrix_driver_set_color_all,
};

uint8_t Led_Colour_Tab[9][3] = {
    {255, 0,   0   },  //红
    {255, 128, 0   },  //橙
    {255, 255, 0   },  //黄
    {0,   255, 0   },  //绿
    {0,   255, 255 },  //青
    {0,   0,   255 },  //蓝
    {128, 0,   255 },  //紫
    {255, 255, 255 }   //白
};

uint8_t Led_Batt_Index_Tab[10] = {
    17       , 18       , 19       , 20       , 21       , 22       , 23       , 24       , 25       , 26
};

uint8_t Led_Point_buf[10] ={ // 当灯光亮度或者速度调到最大或者最小时闪烁
    73      , 81        , 82       , 83
};

uint8_t Led_Wave_Pwm_Tab[128] = {
    0,      4,      8,      12,     16,     20,     24,     28,
    32,     36,     40,     44,     48,     52,     56,     60,
    64,     68,     72,     76,     80,     84,     88,     92,
    96,     100,    104,    108,    112,    116,    120,    124,
    128,    132,    136,    140,    144,    148,    152,    156,
    160,    164,    168,    172,    176,    180,    184,    188,
    192,    196,    200,    204,    208,    212,    216,    220,
    224,    228,    232,    236,    240,    244,    248,    255,

    255,    248,    244,    240,    236,    232,    228,    224,
    220,    216,    212,    208,    204,    200,    196,    192,
    188,    184,    180,    176,    172,    168,    164,    160,
    156,    152,    148,    144,    140,    136,    132,    128,
    124,    120,    116,    112,    108,    104,    100,    96,
    92,     88,     84,     80,     76,     72,     68,     64,
    60,     56,     52,     48,     44,     40,     36,     32,
    28,     24,     20,     16,     12,     8,      4,      0,
};

#if LOGO_LED_ENABLE
static uint8_t LED_Mix_Colour_Tab[256][3] =  {
	{255, 0,   0  },//红 0
	{255, 1,   0  },//   1
	{255, 3,   0  },//   2
	{255, 4,   0  },//   3
	{255, 7,   0  },//   4
	{255, 8,   0  },//   5
	{255, 10,  0  },//   6
	{255, 12,  0  },//   7
	{255, 14,  0  },//   8
	{255, 15,  0  },//   9
	{255, 17,  0  },//   10
	{255, 21,  0  },//   11
	{255, 24,  0  },//   12
	{255, 27,  0  },//   13
	{255, 30,  0  },//   14
	{255, 35,  0  },//   15
	{255, 38,  0  },//   16
	{255, 41,  0  },//   17
	{255, 44,  0  },//   18
	{255, 45,  0  },//   19
	{255, 48,  0  },//   20
	{255, 51,  0  },//   21
	{255, 55,  0  },//   22
	{255, 58,  0  },//   23
	{255, 62,  0  },//橙 24
	{255, 64,  0  },//   25
	{255, 68,  0  },//   26
	{255, 71,  0  },//   27
	{255, 74,  0  },//   28
	{255, 78,  0  },//   29
	{255, 80,  0  },//   30
	{255, 82,  0  },//   31
	{255, 84,  0  },//   32
	{255, 88,  0  },//   33
	{255, 90,  0  },//   34
	{255, 95,  0  },//   35
	{255, 100, 0  },//   36
	{255, 103, 0  },//   37
	{255, 107, 0  },//   38
	{255, 110, 0  },//   39
	{255, 113, 0  },//   40
	{255, 117, 0  },//   41
	{255, 120, 0  },//   42
	{255, 124, 0  },//   43
	{255, 128, 0  },//   44
	{255, 130, 0  },//   45
	{255, 132, 0  },//   46
	{255, 136, 0  },//   47
	{255, 140, 0  },//   48
	{255, 142, 0  },//   49
	{255, 147, 0  },//   50
	{255, 149, 0  },//   51
	{255, 151, 0  },//   52
	{255, 153, 0  },//   53
	{255, 158, 0  },//   54
	{255, 160, 0  },//   55
	{255, 162, 0  },//   56
	{255, 168, 0  },//   57
	{255, 171, 0  },//   58
	{255, 174, 0  },//   59
	{255, 177, 0  },//   60
	{255, 180, 0  },//   61
	{255, 183, 0  },//   62
	{255, 187, 0  },//   63
	{255, 190, 0  },//   64
	{255, 193, 0  },//   65
	{255, 196, 0  },//   66
	{255, 199, 0  },//   67
	{255, 201, 0  },//   68
	{255, 205, 0  },//   69
	{255, 208, 0  },//   70
	{255, 212, 0  },//   71
	{255, 220, 0  },//   72
	{255, 225, 0  },//   73
	{255, 230, 0  },//   74
	{255, 235, 0  },//   75
	{255, 238, 0  },//   76
	{255, 240, 0  },//   77
	{255, 245, 0  },//   78
	{255, 250, 0  },//   79
	{255, 254, 0  },//   80

	{255, 255, 0  },//黄 0
	{245, 255, 0  },//   1
	{231, 255, 0  },//   2
	{224, 255, 0  },//   3
	{217, 255, 0  },//   4
	{203, 255, 0  },//   5
	{196, 255, 0  },//   6
	{189, 255, 0  },//   7
	{175, 255, 0  },//   8
	{168, 255, 0  },//   9
	{161, 255, 0  },//   10
	{147, 255, 0  },//   11
	{140, 255, 0  },//   12
	{133, 255, 0  },//   13
	{126, 255, 0  },//   14
	{119, 255, 0  },//   15
	{105, 255, 0  },//   16
	{98,  255, 0  },//   17
	{91,  255, 0  },//   18
	{84,  255, 0  },//   19
	{77,  255, 0  },//   20
	{70,  255, 0  },//   21
	{63,  255, 0  },//   22
	{56,  255, 0  },//   23
	{49,  255, 0  },//   24
	{42,  255, 0  },//   25
	{35,  255, 0  },//   26
	{28,  255, 0  },//   27
	{21,  255, 0  },//   28
	{14,  255, 0  },//   29
	{7,   255, 0  },//   30

	{0,   255, 0  },//绿 0
	{0,   255, 7  },//   1
	{0,   255, 14 },//   2
	{0,   255, 21 },//   3
	{0,   255, 28 },//   4
	{0,   255, 35 },//   5
	{0,   255, 42 },//   6
	{0,   255, 49 },//   7
	{0,   255, 56 },//   8
	{0,   255, 63 },//   9
	{0,   255, 70 },//   10
	{0,   255, 77 },//   11
	{0,   255, 84 },//   12
	{0,   255, 91 },//   13
	{0,   255, 98 },//   14
	{0,   255, 105},//   15
	{0,   255, 119},//   16
	{0,   255, 126},//   17
	{0,   255, 133},//   18
	{0,   255, 140},//   19
	{0,   255, 154},//   20
	{0,   255, 161},//   21
	{0,   255, 168},//   22
	{0,   255, 182},//   23
	{0,   255, 189},//   24
	{0,   255, 196},//   25
	{0,   255, 210},//   26
	{0,   255, 217},//   27
	{0,   255, 224},//   28
	{0,   255, 238},//   29
	{0,   255, 245},//   30

	{0,   255, 255},//青 0
	{0,   245, 255},//   1
	{0,   231, 255},//   2
	{0,   224, 255},//   3
	{0,   217, 255},//   4
	{0,   203, 255},//   5
	{0,   196, 255},//   6
	{0,   189, 255},//   7
	{0,   175, 255},//   8
	{0,   168, 255},//   9
	{0,   161, 255},//   10
	{0,   147, 255},//   11
	{0,   140, 255},//   12
	{0,   133, 255},//   13
	{0,   126, 255},//   14
	{0,   119, 255},//   15
	{0,   105, 255},//   16
	{0,   98,  255},//   17
	{0,   91,  255},//   18
	{0,   84,  255},//   19
	{0,   77,  255},//   20
	{0,   70,  255},//   21
	{0,   63,  255},//   22
	{0,   56,  255},//   23
	{0,   49,  255},//   24
	{0,   42,  255},//   25
	{0,   35,  255},//   26
	{0,   28,  255},//   27
	{0,   21,  255},//   28
	{0,   14,  255},//   29
	{0,   7,   255},//   30

	{0,   0,   255},//蓝 0
	{5,   0,   255},//   1
	{10,  0,   255},//   2
	{15,  0,   255},//   3
	{20,  0,   255},//   4
	{25,  0,   255},//   5
	{30,  0,   255},//   6
	{35,  0,   255},//   7
	{40,  0,   255},//   8
	{45,  0,   255},//   9
	{50,  0,   255},//   10
	{55,  0,   255},//   11
	{60,  0,   255},//   12
	{65,  0,   255},//   13
	{70,  0,   255},//   14
	{75,  0,   255},//   15
	{85,  0,   255},//   16
	{90,  0,   255},//   17
	{95,  0,   255},//紫 18
	{100, 0,   255},//   19
	{105, 0,   255},//   20
	{110, 0,   255},//   21
	{115, 0,   255},//   22
	{120, 0,   255},//   23
	{125, 0,   255},//   24
	{130, 0,   255},//   25
	{135, 0,   255},//   26
	{140, 0,   255},//   27
	{145, 0,   255},//   28
	{150, 0,   255},//   29
	{155, 0,   255},//   30
	{160, 0,   255},//   31
	{165, 0,   255},//   32
	{170, 0,   255},//   33
	{175, 0,   255},//   34
	{185, 0,   255},//   35
	{180, 0,   255},//   36
	{195, 0,   255},//   37
	{190, 0,   255},//   38
	{200, 0,   255},//   39
	{205, 0,   255},//   40
	{210, 0,   255},//   41
	{215, 0,   255},//   42
	{220, 0,   255},//   43
	{225, 0,   255},//   44
	{230, 0,   255},//   45
	{235, 0,   255},//   46
	{240, 0,   255},//   47
	{245, 0,   255},//   48
	{250, 0,   255},//   49
	{255, 0,   255},//   50

	{255, 0,   255},//粉 0
	{255, 0,   245},//   1
	{255, 0,   231},//   2
	{255, 0,   224},//   3
	{255, 0,   210},//   4
	{255, 0,   203},//   5
	{255, 0,   196},//   6
	{255, 0,   182},//   7
	{255, 0,   175},//   8
	{255, 0,   168},//   9
	{255, 0,   161},//   10
	{255, 0,   147},//   11
	{255, 0,   140},//   12
	{255, 0,   133},//   13
	{255, 0,   126},//   14
	{255, 0,   119},//   15
	{255, 0,   105},//   16
	{255, 0,   98 },//   17
	{255, 0,   91 },//   18
	{255, 0,   84 },//   19
	{255, 0,   77 },//   20
	{255, 0,   70 },//   21
	{255, 0,   63 },//   22
	{255, 0,   56 },//   23
	{255, 0,   49 },//   24
	{255, 0,   42 },//   25
	{255, 0,   35 },//   26
	{255, 0,   28 },//   27
	{255, 0,   21 },//   28
	{255, 0,   14 },//   29
	{255, 0,   7  },//   30
};

uint8_t Logo_Index_Tab[LOGO_LED_SIZE] = {
    84      , 85      , 86      , 87         , 130 ,        131,       132 ,      133
};

uint8_t Logo_Flash_Count = 0x00;
uint8_t Logo_Led_Count = 0x00;
uint8_t Logo_Play_Point = 0;
uint8_t Logo_Pwm_R = 0;
uint8_t Logo_Pwm_G = 0;
uint8_t Logo_Pwm_B = 0;
uint8_t Logo_Pwm_Colour = 0;
/*********************************
            初始化函数
*********************************/
void Logo_Init(void) {
    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        rgb_matrix_set_color(Logo_Index_Tab[i], 0x00, 0x00, 0x00);
    }
    Logo_Play_Point = 64;
    Logo_Pwm_R = 0;
    Logo_Pwm_G = 0;
    Logo_Pwm_B = 0;
    Logo_Pwm_Colour = 0;
}

void Logo_Pwm_Rgb_Updata(uint8_t Pwm) {
    Logo_Pwm_R |= Keyboard_Info.Logo_Saturation;
    Logo_Pwm_G |= Keyboard_Info.Logo_Saturation;
    Logo_Pwm_B |= Keyboard_Info.Logo_Saturation;

    uint16_t Temp_Pwm = 0;
    Temp_Pwm = Logo_Pwm_R * Pwm;
    Logo_Pwm_R = (Temp_Pwm >> 8);

    Temp_Pwm = Logo_Pwm_G * Pwm;
    Logo_Pwm_G = (Temp_Pwm >> 8);

    Temp_Pwm = Logo_Pwm_B * Pwm;
    Logo_Pwm_B = (Temp_Pwm >> 8);
}

void Logo_Pwm_Ds_Updata(uint8_t Pwm) {
    uint16_t Temp_Pwm = 0;
    Temp_Pwm = Logo_Pwm_R * Pwm;
    Logo_Pwm_R = (Temp_Pwm >> 8);
    Logo_Pwm_R |= Keyboard_Info.Logo_Saturation;
    Temp_Pwm = Logo_Pwm_R * Keyboard_Info.Logo_Brightness;
    Logo_Pwm_R = (Temp_Pwm >> 8);

    Temp_Pwm = Logo_Pwm_G * Pwm;
    Logo_Pwm_G = (Temp_Pwm >> 8);
    Logo_Pwm_G |= Keyboard_Info.Logo_Saturation;
    Temp_Pwm = Logo_Pwm_G * Keyboard_Info.Logo_Brightness;
    Logo_Pwm_G = (Temp_Pwm >> 8);

    Temp_Pwm = Logo_Pwm_B * Pwm;
    Logo_Pwm_B = (Temp_Pwm >> 8);
    Logo_Pwm_B |= Keyboard_Info.Logo_Saturation;
    Temp_Pwm = Logo_Pwm_B * Keyboard_Info.Logo_Brightness;
    Logo_Pwm_B = (Temp_Pwm >> 8);
}

/*********************************
            彩色波浪
*********************************/
void Logo_Wave_Rgb_mode_Show(void) {
    if (Logo_Led_Count > LOGO_LED_PLAY_SPEED) {
        Logo_Led_Count = 0;
        if (Keyboard_Info.Logo_Speed != LOGO_MIN_SPEED) {
	        if(Logo_Play_Point >= Keyboard_Info.Logo_Speed) {
		        Logo_Play_Point -= Keyboard_Info.Logo_Speed;
	        } else {
		        Logo_Play_Point = 255 - (Keyboard_Info.Logo_Speed - Logo_Play_Point);
	        }
        }
    }

	uint8_t Temp_Point = Logo_Play_Point;
    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        Logo_Pwm_R = LED_Mix_Colour_Tab[Temp_Point][0];
        Logo_Pwm_G = LED_Mix_Colour_Tab[Temp_Point][1];
        Logo_Pwm_B = LED_Mix_Colour_Tab[Temp_Point][2];

        Logo_Pwm_Rgb_Updata(Keyboard_Info.Logo_Brightness);

        rgb_matrix_set_color(Logo_Index_Tab[i], Logo_Pwm_R, Logo_Pwm_G, Logo_Pwm_B);

        Temp_Point += 12;
		if(Temp_Point >= 255) {
			Temp_Point = 0;
		}
    }
}
/*********************************
            单色波浪
*********************************/
void Logo_Wave_Ds_mode_Show(void) {
    if (Logo_Led_Count > LOGO_LED_PLAY_SPEED) {
        Logo_Led_Count = 0;
        if (Keyboard_Info.Logo_Speed != LOGO_MIN_SPEED) {
	        if(Logo_Play_Point >= Keyboard_Info.Logo_Speed) {
		        Logo_Play_Point -= Keyboard_Info.Logo_Speed;
	        } else {
		        Logo_Play_Point = 127 - (Keyboard_Info.Logo_Speed - Logo_Play_Point);
	        }
        }
    }

	uint8_t Temp_Point = Logo_Play_Point;
    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        Logo_Pwm_R = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][0];
        Logo_Pwm_G = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][1];
        Logo_Pwm_B = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][2];

        Logo_Pwm_Ds_Updata(Led_Wave_Pwm_Tab[Temp_Point]);

        rgb_matrix_set_color(Logo_Index_Tab[i], Logo_Pwm_R, Logo_Pwm_G, Logo_Pwm_B);

        Temp_Point += 8;
		if(Temp_Point >= 127) {
			Temp_Point = 0;
		}
    }
}
/*********************************
            光谱
*********************************/
void Logo_Spectrum_mode_Show(void) {
    if (Logo_Led_Count > LOGO_LED_PLAY_SPEED) {
        Logo_Led_Count = 0;
        if (Keyboard_Info.Logo_Speed != LOGO_MIN_SPEED) {
	        if(Logo_Play_Point >= Keyboard_Info.Logo_Speed) {
		        Logo_Play_Point -= Keyboard_Info.Logo_Speed;
	        } else {
		        Logo_Play_Point = 255 - (Keyboard_Info.Logo_Speed - Logo_Play_Point);
	        }
        }
    }

    Logo_Pwm_R = LED_Mix_Colour_Tab[Logo_Play_Point][0];
    Logo_Pwm_G = LED_Mix_Colour_Tab[Logo_Play_Point][1];
    Logo_Pwm_B = LED_Mix_Colour_Tab[Logo_Play_Point][2];

    Logo_Pwm_Rgb_Updata(Keyboard_Info.Logo_Brightness);

    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        rgb_matrix_set_color(Logo_Index_Tab[i], Logo_Pwm_R, Logo_Pwm_G, Logo_Pwm_B);
    }
}
/*********************************
            呼吸
*********************************/
void Logo_Breath_mode_Show(void) {
    if (Logo_Led_Count > LOGO_LED_PLAY_SPEED) {
        Logo_Led_Count = 0;
        if (Keyboard_Info.Logo_Speed != LOGO_MIN_SPEED) {
	        if(Logo_Play_Point >= Keyboard_Info.Logo_Speed) {
		        Logo_Play_Point -= Keyboard_Info.Logo_Speed;
	        } else {
		        Logo_Play_Point = 127 - (Keyboard_Info.Logo_Speed - Logo_Play_Point);
	        }
        }
    }

    Logo_Pwm_R = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][0];
    Logo_Pwm_G = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][1];
    Logo_Pwm_B = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][2];

    Logo_Pwm_Ds_Updata(Led_Wave_Pwm_Tab[Logo_Play_Point]);

    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        rgb_matrix_set_color(Logo_Index_Tab[i], Logo_Pwm_R, Logo_Pwm_G, Logo_Pwm_B);
    }
}
/*********************************
            常量
*********************************/
void Logo_Light_mode_Show(void) {
    Logo_Pwm_R = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][0];
    Logo_Pwm_G = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][1];
    Logo_Pwm_B = LED_Mix_Colour_Tab[Keyboard_Info.Logo_Colour][2];

    Logo_Pwm_Ds_Updata(255);

    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        rgb_matrix_set_color(Logo_Index_Tab[i], Logo_Pwm_R, Logo_Pwm_G, Logo_Pwm_B);
    }
}
/*********************************
            关闭
*********************************/
void Logo_Off_mode_Show(void) {
    for (uint8_t i = 0; i < LOGO_LED_SIZE; i++) {
        rgb_matrix_set_color(Logo_Index_Tab[i], 0X00, 0X00, 0X00);
    }
}

void Logo_Mode_Show(void) {
    if (Keyboard_Info.Logo_On_Off) {
        Logo_Off_mode_Show();
    } else {
        switch (Keyboard_Info.Logo_Mode) {
            case LOGO_WAVE_RGB_MODE:    Logo_Wave_Rgb_mode_Show();  break;
            case LOGO_WAVE_DS_MODE:     Logo_Wave_Ds_mode_Show();   break;
            case LOGO_SPECTRUM_MODE:    Logo_Spectrum_mode_Show();  break;
            case LOGO_BREATH_MODE:      Logo_Breath_mode_Show();    break;
            case LOGO_LIGHT_MODE:       Logo_Light_mode_Show();     break;
            case LOGO_OFF_MODE:         Logo_Off_mode_Show();       break;
            default:                    Logo_Off_mode_Show();       break;
        }
    }
}

void User_Via_Qmk_Logo_Get_Value(uint8_t *data) {
    // data = [ value_id, value_data ]
    uint8_t *value_id   = &(data[0]);
    uint8_t *value_data = &(data[1]);

    switch (*value_id) {
        case id_qmk_rgb_matrix_brightness: {
            value_data[0] = Keyboard_Info.Logo_Brightness;
            break;
        }
        case id_qmk_rgb_matrix_effect: {
            value_data[0] = Keyboard_Info.Logo_Mode;
            break;
        }
        case id_qmk_rgb_matrix_effect_speed: {
            value_data[0] = Keyboard_Info.Logo_Speed;
            break;
        }
        case id_qmk_rgb_matrix_color: {
            value_data[0] = Keyboard_Info.Logo_Colour;
            value_data[1] = (255 - Keyboard_Info.Logo_Saturation);
            break;
        }
    }
}

void User_Via_Qmk_Logo_Set_Value(uint8_t *data) {
    // data = [ value_id, value_data ]
    uint8_t *value_id   = &(data[0]);
    uint8_t *value_data = &(data[1]);
    switch (*value_id) {
        case id_qmk_rgb_matrix_brightness: {    // 设置亮度 0 ~ 255
            if (value_data[0] > RGB_MATRIX_MAXIMUM_BRIGHTNESS) {
                Keyboard_Info.Logo_Brightness = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
            } else {
                Keyboard_Info.Logo_Brightness = value_data[0];
            }
            break;
        }
        case id_qmk_rgb_matrix_effect: {        // 设置灯光模式
            if (value_data[0] == 0) {
                Keyboard_Info.Logo_On_Off = LOGO_LED_OFF;
            } else {
                Keyboard_Info.Logo_On_Off = LOGO_LED_ON;
                if (value_data[0] <= LOGO_OFF_MODE) {
                    Keyboard_Info.Logo_Mode = value_data[0];
                } else {
                    Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
                }
            }
            break;
        }
        case id_qmk_rgb_matrix_effect_speed: {  // 设置灯光速度
            if (value_data[0] > LOGO_MAX_SPEED) {
                Keyboard_Info.Logo_Speed = LOGO_MAX_SPEED;
            } else {
                Keyboard_Info.Logo_Speed = value_data[0];
            }
            break;
        }
        case id_qmk_rgb_matrix_color: {         // 设置颜色和饱和度
            Keyboard_Info.Logo_Colour = value_data[0];
            Keyboard_Info.Logo_Saturation = (255 - value_data[1]);
            break;
        }
    }
}

void User_Via_Qmk_Logo_Command(uint8_t *data, uint8_t length) {
    // data = [ command_id, channel_id, value_id, value_data ]
    uint8_t *command_id        = &(data[0]);
    uint8_t *value_id_and_data = &(data[2]);

    switch (*command_id) {
        case id_custom_set_value: {
            User_Via_Qmk_Logo_Set_Value(value_id_and_data);
            break;
        }
        case id_custom_get_value: {
            User_Via_Qmk_Logo_Get_Value(value_id_and_data);
            break;
        }
        case id_custom_save: {
            Save_Flash_Set();
            break;
        }
        default: {
            *command_id = id_unhandled;
            break;
        }
    }
}

#endif

#if SIDE_LED_ENABLE
uint8_t Side_Index_Tab[SIDE_LED_SIZE] = {
    92      , 93      , 94      , 95      , 96      , 97      , 98      ,
    99      , 100     , 101     , 102     , 103     , 104     , 105     ,
    106     , 107     , 108     , 109     , 110     , 111     , 112     ,
    113     , 114     , 115     , 116     , 117     , 118     , 119     ,
    120     , 121     , 122     , 123     , 124     , 125     , 91      ,
    90      , 89      , 88
};

uint8_t Side_Led_Count = 0x00;
uint8_t Side_Play_Point = 64;
uint8_t Side_Pwm_R = 0;
uint8_t Side_Pwm_G = 0;
uint8_t Side_Pwm_B = 0;
/*********************************
            初始化函数
*********************************/
void Side_Init(void) {
    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        rgb_matrix_set_color(Side_Index_Tab[i], 0x00, 0x00, 0x00);
    }
    Side_Play_Point = 0;
    Side_Pwm_R = 0;
    Side_Pwm_G = 0;
    Side_Pwm_B = 0;
}

void Side_Pwm_Rgb_Updata(uint8_t Pwm) {
    Side_Pwm_R |= Keyboard_Info.Side_Saturation;
    Side_Pwm_G |= Keyboard_Info.Side_Saturation;
    Side_Pwm_B |= Keyboard_Info.Side_Saturation;

    uint16_t Temp_Pwm = 0;
    Temp_Pwm = Side_Pwm_R * Pwm;
    Side_Pwm_R = (Temp_Pwm >> 8);

    Temp_Pwm = Side_Pwm_G * Pwm;
    Side_Pwm_G = (Temp_Pwm >> 8);

    Temp_Pwm = Side_Pwm_B * Pwm;
    Side_Pwm_B = (Temp_Pwm >> 8);
}

void Side_Pwm_Ds_Updata(uint8_t Pwm) {
    uint16_t Temp_Pwm = 0;
    Temp_Pwm = Side_Pwm_R * Pwm;
    Side_Pwm_R = (Temp_Pwm >> 8);
    Side_Pwm_R |= Keyboard_Info.Side_Saturation;
    Temp_Pwm = Side_Pwm_R * Keyboard_Info.Side_Brightness;
    Side_Pwm_R = (Temp_Pwm >> 8);

    Temp_Pwm = Side_Pwm_G * Pwm;
    Side_Pwm_G = (Temp_Pwm >> 8);
    Side_Pwm_G |= Keyboard_Info.Side_Saturation;
    Temp_Pwm = Side_Pwm_G * Keyboard_Info.Side_Brightness;
    Side_Pwm_G = (Temp_Pwm >> 8);

    Temp_Pwm = Side_Pwm_B * Pwm;
    Side_Pwm_B = (Temp_Pwm >> 8);
    Side_Pwm_B |= Keyboard_Info.Side_Saturation;
    Temp_Pwm = Side_Pwm_B * Keyboard_Info.Side_Brightness;
    Side_Pwm_B = (Temp_Pwm >> 8);
}
/*********************************
            彩色波浪
*********************************/
void Side_Wave_Rgb_mode_Show(void) {
    if (Side_Led_Count > SIDE_LED_PLAY_SPEED) {
        Side_Led_Count = 0;
        if (Keyboard_Info.Side_Speed != SIDE_MIN_SPEED) {
	        if(Side_Play_Point >= Keyboard_Info.Side_Speed) {
		        Side_Play_Point -= Keyboard_Info.Side_Speed;
	        } else {
		        Side_Play_Point = 255 - (Keyboard_Info.Side_Speed - Side_Play_Point);
	        }
        }
    }

	uint8_t Temp_Point = Side_Play_Point;
    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        Side_Pwm_R = LED_Mix_Colour_Tab[Temp_Point][0];
        Side_Pwm_G = LED_Mix_Colour_Tab[Temp_Point][1];
        Side_Pwm_B = LED_Mix_Colour_Tab[Temp_Point][2];

        Side_Pwm_Rgb_Updata(Keyboard_Info.Side_Brightness);

        rgb_matrix_set_color(Side_Index_Tab[i], Side_Pwm_R, Side_Pwm_G, Side_Pwm_B);

        Temp_Point += 8;
		if(Temp_Point >= 255) {
			Temp_Point = 0;
		}
    }
}
/*********************************
            单色波浪
*********************************/
void Side_Wave_Ds_mode_Show(void) {
    if (Side_Led_Count > SIDE_LED_PLAY_SPEED) {
        Side_Led_Count = 0;
        if (Keyboard_Info.Side_Speed != SIDE_MIN_SPEED) {
	        if(Side_Play_Point >= Keyboard_Info.Side_Speed) {
		        Side_Play_Point -= Keyboard_Info.Side_Speed;
	        } else {
		        Side_Play_Point = 127 - (Keyboard_Info.Side_Speed - Side_Play_Point);
	        }
        }
    }

	uint8_t Temp_Point = Side_Play_Point;
    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        Side_Pwm_R = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][0];
        Side_Pwm_G = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][1];
        Side_Pwm_B = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][2];

        Side_Pwm_Ds_Updata(Led_Wave_Pwm_Tab[Temp_Point]);

        rgb_matrix_set_color(Side_Index_Tab[i], Side_Pwm_R, Side_Pwm_G, Side_Pwm_B);

        Temp_Point += 8;
		if(Temp_Point >= 127) {
			Temp_Point = 0;
		}
    }
}
/*********************************
            光谱
*********************************/
void Side_Spectrum_mode_Show(void) {
    if (Side_Led_Count > SIDE_LED_PLAY_SPEED) {
        Side_Led_Count = 0;
        if (Keyboard_Info.Side_Speed != SIDE_MIN_SPEED) {
	        if(Side_Play_Point >= Keyboard_Info.Side_Speed) {
		        Side_Play_Point -= Keyboard_Info.Side_Speed;
	        } else {
		        Side_Play_Point = 255 - (Keyboard_Info.Side_Speed - Side_Play_Point);
	        }
        }
    }

    Side_Pwm_R = LED_Mix_Colour_Tab[Side_Play_Point][0];
    Side_Pwm_G = LED_Mix_Colour_Tab[Side_Play_Point][1];
    Side_Pwm_B = LED_Mix_Colour_Tab[Side_Play_Point][2];

    Side_Pwm_Rgb_Updata(Keyboard_Info.Side_Brightness);

    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        rgb_matrix_set_color(Side_Index_Tab[i], Side_Pwm_R, Side_Pwm_G, Side_Pwm_B);
    }
}
/*********************************
            呼吸
*********************************/
void Side_Breath_mode_Show(void) {
    if (Side_Led_Count > SIDE_LED_PLAY_SPEED) {
        Side_Led_Count = 0;
        if (Keyboard_Info.Side_Speed != SIDE_MIN_SPEED) {
	        if(Side_Play_Point >= Keyboard_Info.Side_Speed) {
		        Side_Play_Point -= Keyboard_Info.Side_Speed;
	        } else {
		        Side_Play_Point = 127 - (Keyboard_Info.Side_Speed - Side_Play_Point);
	        }
        }
    }

    Side_Pwm_R = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][0];
    Side_Pwm_G = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][1];
    Side_Pwm_B = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][2];

    Side_Pwm_Ds_Updata(Led_Wave_Pwm_Tab[Side_Play_Point]);

    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        rgb_matrix_set_color(Side_Index_Tab[i], Side_Pwm_R, Side_Pwm_G, Side_Pwm_B);
    }
}
/*********************************
            常亮
*********************************/
void Side_Light_mode_Show(void) {
    Side_Pwm_R = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][0];
    Side_Pwm_G = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][1];
    Side_Pwm_B = LED_Mix_Colour_Tab[Keyboard_Info.Side_Colour][2];

    Side_Pwm_Ds_Updata(255);

    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        rgb_matrix_set_color(Side_Index_Tab[i], Side_Pwm_R, Side_Pwm_G, Side_Pwm_B);
    }
}
/*********************************
            关闭
*********************************/
void Side_Off_mode_Show(void) {
    for (uint8_t i = 0; i < SIDE_LED_SIZE; i++) {
        rgb_matrix_set_color(Side_Index_Tab[i], 0X00, 0X00, 0X00);
    }
}

void Side_Mode_Show(void) {
    if (Keyboard_Info.Side_On_Off) {
        Side_Off_mode_Show();
    } else {
        switch (Keyboard_Info.Side_Mode) {
            case SIDE_WAVE_RGB_MODE:    Side_Wave_Rgb_mode_Show();  break;
            case SIDE_WAVE_DS_MODE:     Side_Wave_Ds_mode_Show();   break;
            case SIDE_SPECTRUM_MODE:    Side_Spectrum_mode_Show();  break;
            case SIDE_BREATH_MODE:      Side_Breath_mode_Show();    break;
            case SIDE_LIGHT_MODE:       Side_Light_mode_Show();     break;
            case SIDE_OFF_MODE:         Side_Off_mode_Show();       break;
            default:                    Side_Off_mode_Show();       break;
        }
    }
}

void User_Via_Qmk_Side_Get_Value(uint8_t *data) {
    // data = [ value_id, value_data ]
    uint8_t *value_id   = &(data[0]);
    uint8_t *value_data = &(data[1]);

    switch (*value_id) {
        case id_qmk_rgb_matrix_brightness: {
            value_data[0] = Keyboard_Info.Side_Brightness;
            break;
        }
        case id_qmk_rgb_matrix_effect: {
            value_data[0] = Keyboard_Info.Side_Mode;
            break;
        }
        case id_qmk_rgb_matrix_effect_speed: {
            value_data[0] = Keyboard_Info.Side_Speed;
            break;
        }
        case id_qmk_rgb_matrix_color: {
            value_data[0] = Keyboard_Info.Side_Colour;
            value_data[1] = (255 - Keyboard_Info.Side_Saturation);
            break;
        }
    }
}

void User_Via_Qmk_Side_Set_Value(uint8_t *data) {
    // data = [ value_id, value_data ]
    uint8_t *value_id   = &(data[0]);
    uint8_t *value_data = &(data[1]);
    switch (*value_id) {
        case id_qmk_rgb_matrix_brightness: {    // 设置亮度 0 ~ 255
            if (value_data[0] > RGB_MATRIX_MAXIMUM_BRIGHTNESS) {
                Keyboard_Info.Side_Brightness = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
            } else {
                Keyboard_Info.Side_Brightness = value_data[0];
            }
            break;
        }
        case id_qmk_rgb_matrix_effect: {        // 设置灯光模式
            if (value_data[0] == 0) {
                Keyboard_Info.Side_On_Off = SIDE_LED_OFF;
            } else {
                Keyboard_Info.Side_On_Off = SIDE_LED_ON;
                if (value_data[0] <= SIDE_OFF_MODE) {
                    Keyboard_Info.Side_Mode = value_data[0];
                } else {
                    Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
                }
            }
            break;
        }
        case id_qmk_rgb_matrix_effect_speed: {  // 设置灯光速度
            if (value_data[0] > SIDE_MAX_SPEED) {
                Keyboard_Info.Side_Speed = SIDE_MAX_SPEED;
            } else {
                Keyboard_Info.Side_Speed = value_data[0];
            }
            break;
        }
        case id_qmk_rgb_matrix_color: {         // 设置颜色和饱和度
            Keyboard_Info.Side_Colour = value_data[0];
            Keyboard_Info.Side_Saturation = (255 - value_data[1]);
            break;
        }
    }
}

void User_Via_Qmk_Side_Command(uint8_t *data, uint8_t length) {
    // data = [ command_id, channel_id, value_id, value_data ]
    uint8_t *command_id        = &(data[0]);
    uint8_t *value_id_and_data = &(data[2]);

    switch (*command_id) {
        case id_custom_set_value: {
            User_Via_Qmk_Side_Set_Value(value_id_and_data);
            break;
        }
        case id_custom_get_value: {
            User_Via_Qmk_Side_Get_Value(value_id_and_data);
            break;
        }
        case id_custom_save: {
            Save_Flash_Set();
            break;
        }
        default: {
            *command_id = id_unhandled;
            break;
        }
    }
}

#endif

#define LED_BAT_INDEX       (79)
#define LED_CAP_INDEX       (48)
#define LED_WIN_L_INDEX     (75)

#define LED_BLE_1_INDEX     (33)
#define LED_BLE_2_INDEX     (34)
#define LED_BLE_3_INDEX     (35)
#define LED_2P4G_INDEX      (36)
#define LED_USB_INDEX       (37)

led_config_t g_led_config = { {
	{ 0        , 1        , 2        , 3        , 4        , 5        , 6        , 7        , 8        , 9        , 10       , 11       , 12       , 13       , 14       , 15     },
	{ 16       , 17       , 18       , 19       , 20       , 21       , 22       , 23       , 24       , 25       , 26       , 27       , 28       , 29       , 30       , 31     },
	{ 32       , 33       , 34       , 35       , 36       , 37       , 38       , 39       , 40       , 41       , 42       , 43       , 44       , 45       , 46       , 47     },
	{ 48       , 49       , 50       , 51       , 52       , 53       , 54       , 55       , 56       , 57       , 58       , 59       , NO_LED   , 60       , NO_LED   , NO_LED },
	{ 61       , NO_LED   , 62       , 63       , 64       , 65       , 66       , 67       , 68       , 69       , 70       , 71       , NO_LED   , 72       , 73       , NO_LED },
	{ 74       , 75       , 76       , NO_LED   , NO_LED   , 77       , NO_LED   , NO_LED   , NO_LED   , 78       , 79       , NO_LED   , 80       , 81       , 82       , 83     }
}, {
    { 0 , 10 },  { 17, 10 },  { 31, 10 },  { 45, 10 }, { 59, 10 }, { 76, 10 }, { 90,  10 }, { 104, 10 }, { 118, 10 }, { 135, 10 }, { 149, 10 }, { 163, 10 }, { 177, 10 }, { 194, 10 }, { 210, 10 }, { 224, 10 },
    { 0 , 20 },  { 15, 20 },  { 30, 20 },  { 45, 20 }, { 60, 20 }, { 75, 20 }, { 90,  20 }, { 105, 20 }, { 120, 20 }, { 135, 20 }, { 150, 20 }, { 165, 20 }, { 180, 20 }, { 200, 20 }, { 210, 20 }, { 224, 20 },
    { 3 , 30 },  { 20, 30 },  { 35, 30 },  { 49, 30 }, { 63, 30 }, { 77, 30 }, { 91,  30 }, { 105, 30 }, { 119, 30 }, { 133, 30 }, { 147, 30 }, { 161, 30 }, { 175, 30 }, { 198, 30 }, { 210, 30 }, { 224, 30 },
    { 3 , 40 },  { 25, 40 },  { 40, 40 },  { 55, 40 }, { 70, 40 }, { 85, 40 }, { 100, 40 }, { 115, 40 }, { 130, 40 }, { 145, 40 }, { 160, 40 }, { 175, 40 },              { 203, 40 },
    { 7 , 50 },               { 34, 50 },  { 49, 50 }, { 64, 50 }, { 79, 50 }, { 94,  50 }, { 105, 50 }, { 124, 50 }, { 139, 50 }, { 154, 50 }, { 169, 50 },              { 184, 50 }, { 210, 50 },
    { 0 , 60 },  { 17, 60 },  { 34, 60 },                          { 95, 60 },                                        { 152, 60 }, { 169, 60 },              { 186, 60 }, { 195, 60 }, { 210, 60 }, { 224, 60 },

    { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, 
    { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, 
    { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, 
    { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 },
    { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }, { 225, 65 }
}, {
    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,      1,
    1,      1,  1,  1,  1,  1,  1,  1,  1,  1,  1,      1,  1,
    1,  1,  1,          1,              1,  1,      1,  1,  1,  1,

    0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0
} };

void Led_Rf_Mode_Show(void) {
    uint8_t Temp_Colour = 0,Led_Index = 0;
    if (Keyboard_Info.Key_Mode == QMK_BLE_MODE) {
        if (Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_1) {
            Temp_Colour = 7;
            Led_Index = LED_BLE_1_INDEX;
        } else if (Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_2) {
            Temp_Colour = 7;
            Led_Index = LED_BLE_2_INDEX;
        } else if (Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_3) {
            Temp_Colour = 7;
            Led_Index = LED_BLE_3_INDEX;
        }
    } else if (Keyboard_Info.Key_Mode == QMK_2P4G_MODE) {
        Temp_Colour = 7;
        Led_Index = LED_2P4G_INDEX;
    }

    if (Keyboard_Status.System_Connect_Status == KB_MODE_CONNECT_PAIR) {
        if (Systick_Led_Count < 10) {
            rgb_matrix_set_color(Led_Index, Led_Colour_Tab[Temp_Colour][0], Led_Colour_Tab[Temp_Colour][1], Led_Colour_Tab[Temp_Colour][2]);
        } else {
            rgb_matrix_set_color(Led_Index, 0, 0, 0);
        }

        if (Systick_Led_Count >= 20) {
            Systick_Led_Count = 0;
        }
    } else if (Keyboard_Status.System_Connect_Status == KB_MODE_CONNECT_RETURN) {
        if (Systick_Led_Count < 25) {
            rgb_matrix_set_color(Led_Index, Led_Colour_Tab[Temp_Colour][0], Led_Colour_Tab[Temp_Colour][1], Led_Colour_Tab[Temp_Colour][2]);
        } else {
            rgb_matrix_set_color(Led_Index, 0, 0, 0);
        }

        if (Systick_Led_Count >= 50) {
            Systick_Led_Count = 0;
        }
    } else {
        rgb_matrix_set_color(Led_Index, Led_Colour_Tab[Temp_Colour][0], Led_Colour_Tab[Temp_Colour][1], Led_Colour_Tab[Temp_Colour][2]);

        if (Systick_Led_Count >= 240) {
            Systick_Led_Count = 0;
            Led_Rf_Pair_Flg = false;
            if (Keyboard_Info.Key_Mode == QMK_BLE_MODE) {
                User_Batt_Send_Spi = true;
            }
        }
    }
}

void Led_Power_Low_Show(void) {
    for (uint8_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) {
        rgb_matrix_set_color(i, 0, 0, 0);
    }

    if (Systick_Led_Count < 25) {
        rgb_matrix_set_color(LED_BAT_INDEX, U_PWM, 0X00, 0X00);
    } else {
        rgb_matrix_set_color(LED_BAT_INDEX, 0X00, 0X00, 0X00);
    }

    if (Systick_Led_Count >= 50) {
        Systick_Led_Count = 0;
    }
}

void Led_Point_Flash_Show(void) {
    if (Systick_Led_Count < 25) {
        if (Led_Point_Count) {
            for(uint8_t i = 0; i < 4; i++){
                rgb_matrix_set_color(Led_Point_buf[i], U_PWM, U_PWM, U_PWM);
            }
        } else {
            for(uint8_t i = 0; i < 4; i++){
                rgb_matrix_set_color(Led_Point_buf[i], U_PWM, U_PWM, 0X00);
            }
        }
    } else {
        for(uint8_t i = 0; i < 4; i++){
                rgb_matrix_set_color(Led_Point_buf[i], 0X00, 0X00, 0X00);
            }
    }

    if (Systick_Led_Count >= 50) {
        Systick_Led_Count = 0;

        if (Led_Point_Count) {
            Led_Point_Count--;
        } else if (Mac_Win_Point_Count) {
            Mac_Win_Point_Count--;
        }
    }
}

void Led_Batt_Number_Show(void) {
    for (uint8_t i = 0; i < RGB_MATRIX_BACKLIGHT_COUNT; i++) {
        rgb_matrix_set_color(i, 0, 0, 0);
    }

    // /*********充电流水灯*********/
    // if (es_stdby_pin_state == 1) {
    //     if (Batt_Led_Count >= 2) {
    //         Batt_Led_Count = 0;

    //         if (User_Key_Batt_Count > 3) {
    //             User_Key_Batt_Count -= 3;
    //         } else {
    //             User_Key_Batt_Count = 127;
    //         }
    //     }
    //     uint8_t Tmep_Pwm = User_Key_Batt_Count;

    //     for (uint8_t i = 0; i < 10; i++) {
    //         rgb_matrix_set_color(Led_Batt_Index_Tab[i], 0X00, Led_Wave_Pwm_Tab[Tmep_Pwm], 0X00);
    //         Tmep_Pwm += 8;
    //         if (Tmep_Pwm >= 128) {
    //             Tmep_Pwm -= 128;
    //         }
    //     }
    // }

    if (es_stdby_pin_state == 1) {                      //充电
        uint8_t Colour_R = 0, Colour_G = 0, Colour_B = 0;
        uint8_t Temp_Count = (Keyboard_Info.Batt_Number / 10) + 1;
        if (Temp_Count < 3) {                           //红色
            Colour_R = 0XFF;    Colour_G = 0X00;    Colour_B = 0X00;
        } else if (Temp_Count < 5) {                    //黄色
            Colour_R = 0XFF;    Colour_G = 0XFF;    Colour_B = 0X00;
        } else {                                        //绿色
            if (Temp_Count > 10) {
                Temp_Count = 10;
            }
            Colour_R = 0X00;    Colour_G = 0XFF;    Colour_B = 0X00;
        }
        for (uint8_t i = 0; i < Temp_Count; i++) {
            rgb_matrix_set_color(Led_Batt_Index_Tab[i], Colour_R, Colour_G, Colour_B);
        }
        //rgb_matrix_set_color(LED_BAT_INDEX, 0XFF, 0X00, 0X00);
    } else if (es_stdby_pin_state == 2) {               //充满
        for (uint8_t i = 0; i < 10; i++) {
            rgb_matrix_set_color(Led_Batt_Index_Tab[i], 0X00, 0XFF, 0X00);
        }
        // rgb_matrix_set_color(LED_BAT_INDEX, 0X00, 0XFF, 0X00);
    } else {                                            //未充电
        uint8_t Colour_R = 0, Colour_G = 0, Colour_B = 0;
        uint8_t Temp_Count = (Keyboard_Info.Batt_Number / 10) + 1;
        if (Temp_Count < 3) {                           //红色
            Colour_R = 0XFF;    Colour_G = 0X00;    Colour_B = 0X00;
        } else if (Temp_Count < 5) {                    //黄色
            Colour_R = 0XFF;    Colour_G = 0XFF;    Colour_B = 0X00;
        } else {                                        //绿色
            if (Temp_Count > 10) {
                Temp_Count = 10;
            }
            Colour_R = 0X00;    Colour_G = 0XFF;    Colour_B = 0X00;
        }

        for (uint8_t i = 0; i < Temp_Count; i++) {
            rgb_matrix_set_color(Led_Batt_Index_Tab[i], Colour_R, Colour_G, Colour_B);
        }
    }
}

void User_Get_Led_Power_Status(void) {
#if (LOGO_LED_ENABLE && SIDE_LED_ENABLE)
    if ( ((Keyboard_Info.Led_On_Off == INIT_LED_OFF)  || (rgb_matrix_get_val() <= 0)) &&
         ((Keyboard_Info.Logo_On_Off == LOGO_LED_OFF) || (Keyboard_Info.Logo_Brightness <= 0)) &&
         ((Keyboard_Info.Side_On_Off == SIDE_LED_OFF) || ((Keyboard_Info.Side_Brightness <= 0)) )) {
        Led_Point_Sleep = true;
    } else {
        Led_Point_Sleep = false;
    }
#elif (LOGO_LED_ENABLE)
    if ( ((Keyboard_Info.Led_On_Off == INIT_LED_OFF)  || (rgb_matrix_get_val() <= 0)) &&
         ((Keyboard_Info.Logo_On_Off == LOGO_LED_OFF) || (Keyboard_Info.Logo_Brightness <= 0)) ) {
        Led_Point_Sleep = true;
    } else {
        Led_Point_Sleep = false;
    }
#else
    if ((Keyboard_Info.Led_On_Off == INIT_LED_OFF) || (rgb_matrix_get_val() <= 0)) {
        Led_Point_Sleep = true;
    } else {
        Led_Point_Sleep = false;
    }
#endif

    if (Keyboard_Info.Led_On_Off == INIT_LED_OFF) {
        for (uint8_t i = 0; i < RGB_MATRIX_BACKLIGHT_COUNT; i++) {
                rgb_matrix_set_color(i, 0, 0, 0);
        }
    }
}

/**********指示灯**********/
bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) {
    User_Get_Led_Power_Status();
	
#if LOGO_LED_ENABLE
    if (!User_Power_Low) {
        Logo_Mode_Show();
    }
#endif

    if (User_Power_Low) {
        Led_Point_Sleep = false;
        Led_Power_Low_Show();
    } else if (Led_Rf_Pair_Flg && (Keyboard_Info.Key_Mode != QMK_USB_MODE)) {
        Led_Point_Sleep = false;
        Led_Rf_Mode_Show();
    } else if (Led_Point_Count) {
        Led_Point_Sleep = false;
        Led_Point_Flash_Show();    
	} else if (Usb_If_Ok && (Keyboard_Info.Key_Mode == QMK_USB_MODE)) {
        Led_Point_Sleep = false;
        rgb_matrix_set_color(LED_USB_INDEX, U_PWM, U_PWM, U_PWM);
    } else {
        Systick_Led_Count = 0;

        if (Keyboard_Info.Key_Mode == QMK_USB_MODE) {
            if (host_keyboard_led_state().caps_lock && Usb_If_Ok_Led) {
                Led_Point_Sleep = false;
                rgb_matrix_set_color(LED_CAP_INDEX, U_PWM, U_PWM, U_PWM);
            }
        } else {
            if (Keyboard_Status.System_Led_Status & 0x02) {
                Led_Point_Sleep = false;
                rgb_matrix_set_color(LED_CAP_INDEX, U_PWM, U_PWM, U_PWM);
            }
        }

        if (Keyboard_Info.Win_Lock) {
            if(Keyboard_Info.Key_Mode == QMK_USB_MODE){
                if(Usb_If_Ok_Led){
                    Led_Point_Sleep = false;
                    rgb_matrix_set_color(LED_WIN_L_INDEX, U_PWM, U_PWM, U_PWM);
                }
            }else{
                Led_Point_Sleep = false;
                rgb_matrix_set_color(LED_WIN_L_INDEX, U_PWM, U_PWM, U_PWM);
            }
        }

        if (Key_Fn_Status) {     // 按下FN键时，相对应的Q/W/E/R/T键常亮起，表示当前连接模式
            switch (Keyboard_Info.Key_Mode) {
                case QMK_BLE_MODE: {
                    switch (Keyboard_Info.Ble_Channel) {
                        case QMK_BLE_CHANNEL_1: rgb_matrix_set_color(LED_BLE_1_INDEX, U_PWM, U_PWM, U_PWM); break;
                        case QMK_BLE_CHANNEL_2: rgb_matrix_set_color(LED_BLE_2_INDEX, U_PWM, U_PWM, U_PWM); break;
                        case QMK_BLE_CHANNEL_3: rgb_matrix_set_color(LED_BLE_3_INDEX, U_PWM, U_PWM, U_PWM); break;
                        default:                                                                            break;
                    }
                } break;
                case QMK_2P4G_MODE:             rgb_matrix_set_color(LED_2P4G_INDEX, U_PWM, U_PWM, U_PWM);  break;
                case QMK_USB_MODE:              rgb_matrix_set_color(LED_USB_INDEX,  U_PWM, U_PWM, U_PWM);  break;
                default:                                                                                    break;
            }
            Led_Point_Sleep = false;
        }
    }

    /******充电红色指示灯亮10s******/
    if (((es_stdby_pin_state == 1) || (es_stdby_pin_state == 2)) && User_Key_Batt_LED_Flag) {
        Led_Point_Sleep = false;
        rgb_matrix_set_color(LED_BAT_INDEX, U_PWM, 0X00, 0X00);
    }

    if (User_Key_Batt_Num_Show && (!User_Power_Low)) {
        Led_Point_Sleep = false;
        Led_Batt_Number_Show();
    }

#if SIDE_LED_ENABLE
    if (!User_Power_Low) {
        Side_Mode_Show();
    }
#endif
    return false;
    
}

/*********************************************************/
/************************ADC******************************/
const md_adc_initial adc_initStruct =    /**< ADC init structure */
{
    MD_ADC_CFG_ALIGN_RIGHT,     //Data alignment（数据对齐）
    MD_ADC_CFG_RSEL_12BIT,      //Data resolution（）
    MD_ADC_MODE_NCHS,           //Regular or Injected
    MD_ADC_CFG_CM_SINGLE,       //Single mode
    MD_ADC_NCHS1_NSL_1CON,      /*sample count  采样通道数量*/
    MD_ADC_SMPT1_CKDIV_DIV6,    //ADC prescale（ADC预分频）
};

void User_Adc_Init(void) {  //ES_BATT_ADC_IO
    md_gpio_inittypedef gpiox;

    gpiox.OutputType = MD_GPIO_OUTPUT_PUSHPULL;
    gpiox.Pull = MD_GPIO_PULL_FLOATING;
    gpiox.OutDrive = MD_GPIO_DRIVING_8MA;
    gpiox.Function = MD_GPIO_AF0;
    gpiox.Mode = MD_GPIO_MODE_ANALOG;
    gpiox.Pin = MD_GPIO_PIN_4;
    md_gpio_init(GPIOC, &gpiox);

    md_rcu_enable_adc(RCU);//使能ADC同步制动
    md_adc_calibration(ADC, (md_adc_initial *)(&adc_initStruct));//ADC校准
    md_adc_set_sampletime_channel_14(ADC, 0x40);            //设置ADC通道

    md_adc_init(ADC, (md_adc_initial *)(&adc_initStruct));

    while ((ADC->RIF & 0x1) == 0);

    md_adc_set_normal_sequence_length(ADC, adc_initStruct.Cnt);//采样次数
    md_adc_set_normal_sequence_selection_1th(ADC, MD_ADC_NCHS1_NS1_CH14);

    md_adc_set_start_normal(ADC, MD_ADC_CON_NSTART_START_REGULAR);//开始ADC采样
}

void User_Adc_Deinit(void) {
    md_rcu_enable_adc_reset(RCU);
    md_rcu_disable_adc_reset(RCU);
    md_rcu_disable_adc(RCU);
}
/*********************************************************/

/************************SYSTIME**************************/
void User_Systime_Init(void) {                      //中断频率2ms
    md_rcu_enable_bs16t1(RCU);                      //基本定时器 16 位(BS16T1)包含一个 16 位计数器
    BS16T1->PRES = 48 - 1;                          //预分频寄存器
    BS16T1->AR = 2000;                              //自动重载计数器
    BS16T1->IER = 0x1;                              //中断开启寄存器
    BS16T1->CON1 = 0x1;                             //控制寄存器,开启计数计时器
	NVIC_SetPriority(BS16T1_IRQn, 2);               //将一个优先级可配置的中断或异常的优先级设置为级别2
	NVIC_EnableIRQ(BS16T1_IRQn);                    //允许中断和异常
}

void User_Systime_Deinit(void) {
    md_rcu_enable_bs16t1_reset(RCU);
    md_rcu_disable_bs16t1_reset(RCU);
    md_rcu_disable_bs16t1(RCU);
}
/*********************************************************/

/************************USB 插件**************************/
void User_Usb_Init(void) {  //中断频率2ms
    /*Using USB_SOF to calibrate the internal clock*/
    md_rcu_enable_csu(RCU);
    CSU->CON |= CSU_CON_AUTOEN_MSK;
    CSU->CON |= CSU_CON_CNTEN_MSK;
}

void es_restart_usb_driver(void) {
    md_rcu_enable_usb(RCU);
    ald_usb_device_components_init();
	USB->TXIER = 0x7F;
	USB->RXIER = 0x7E;
	USB->IER = 0x2F;
	usb_lld_connect_bus(0);
	ald_usb_int_register();
}

void Usb_Disconnect(void) {
	/*USB 复位*/
    ald_usb_int_unregister();
    usb_lld_disconnect_bus(0);

    md_rcu_enable_usb_reset(RCU);
    md_rcu_disable_usb_reset(RCU);
    md_rcu_disable_usb(RCU);
}

void User_Usb_Deinit(void) {
    md_rcu_enable_csu_reset(RCU);
    md_rcu_disable_csu_reset(RCU);
    md_rcu_disable_csu(RCU);
}
/*********************************************************/

/************************休眠*****************************/
void Init_Gpio_Infomation(void) {
    /* ON LED POWER*/
    gpio_write_pin_low(ES_LED_POWER_IO);
    gpio_set_pin_output(ES_LED_POWER_IO);
    gpio_write_pin_low(ES_LED_POWER_IO);

    /* ENABLE 升压*/
    gpio_write_pin_high(ES_SDB_POWER_IO);
    gpio_set_pin_output(ES_SDB_POWER_IO);
    gpio_write_pin_high(ES_SDB_POWER_IO);

    /* 输出唤醒IO高电平*/
    gpio_write_pin_high(ES_WUKEUP_IO);
    gpio_set_pin_output(ES_WUKEUP_IO);
    gpio_write_pin_high(ES_WUKEUP_IO);

    //STDBT
    gpio_set_pin_input_high(ES_BATT_STDBY_IO);  //输入上拉

    //USB POWER
    gpio_set_pin_input(ES_USB_POWER_IO);    //输入下拉

    gpio_set_pin_input_high(WHEEL_ZA_IO);
    gpio_set_pin_input_high(WHEEL_ZB_IO);
	// 拨动开关切换
    gpio_set_pin_input_high(MAC_WIN_IO);
    gpio_set_pin_input_high(MODE_2P4G_IO);
    gpio_set_pin_input_high(MODE_BLE_IO);

    md_gpio_inittypedef gpiox;

    /*设置 PA4 为输入*/
    gpiox.Pin   = MD_GPIO_PIN_4;
    gpiox.Mode  = MD_GPIO_MODE_INPUT;
    gpiox.OutputType = MD_GPIO_OUTPUT_PUSHPULL;
    gpiox.Pull  = MD_GPIO_PULL_DOWN;
    gpiox.OutDrive = MD_GPIO_DRIVING_8MA;
    gpiox.Function = MD_GPIO_AF0;
    md_gpio_init(GPIOA, &gpiox);

    /*注册 PA4 中断*/
    md_exti_set_interrupt_pin_0_7(EXTI, MD_EXTI_GPIOA4);
    md_exti_enable_it_gpio_pin(EXTI, MD_EXTI_GPIO4);
    md_exti_enable_rising_edge_trigger(EXTI, MD_EXTI_GPIO4);
    md_exti_enable_falling_edge_trigger(EXTI, MD_EXTI_GPIO4);

	NVIC_SetPriority(EXTI_4to15_IRQn, 3);
    NVIC_EnableIRQ((IRQn_Type) EXTI_4to15_IRQn);   /* EXTI_4to15_IRQn interrupt */
}

void Init_Batt_Infomation(void){
    if (gpio_read_pin(ES_USB_POWER_IO)) {   //如果上电的时候插了USB，则从eeprom里面将电池电量数据取出来
        User_Batt_BaiFen = Keyboard_Info.Batt_Number;
        User_Batt_Old_BaiFen = User_Batt_BaiFen;
        User_Batt_Power_Up = false;
    } else {                                //没有插入USB线的时候就默认快速扫描5此初始化电池电量
        User_Batt_Power_Up = true;
    }
    User_Batt_10ms_Count = 0;
    User_Adc_Batt_Count = 0;
    User_Batt_Time_15S_Count = 0;
    User_Power_Low = false;
    User_Power_Low_Count = 0;

    U16_Buff_Clear(User_Adc_Batt, USER_BATT_SCAN_COUNT);
    U16_Buff_Clear(User_Scan_Batt, USER_BATT_SCAN_COUNT);

    User_Batt_Power_Up_Delay_100ms_Count = 0;
    User_Batt_Power_Up_Delay = true;
}

void notify_usb_device_state_change_user(enum usb_device_state usb_device_state)  {
    if (Keyboard_Info.Key_Mode == QMK_USB_MODE) {
        if(usb_device_state == USB_DEVICE_STATE_CONFIGURED) {
            Usb_If_Ok = true;//usb枚举完成
            Usb_If_Ok_Led = true;
            Usb_If_Ok_Delay = 0;
        } else {
            Usb_If_Ok = false;
		    Usb_If_Ok_Led = false;
        }
    } else {
        Usb_If_Ok = false;
	    Usb_If_Ok_Led = false;
    }
}

/*先将IO配置成需要休眠的状态*/
void User_Sleep(void) {
    /* ON LED POWER*/
    gpio_set_pin_output(ES_LED_POWER_IO);
    gpio_write_pin_low(ES_LED_POWER_IO);

    /* ENABLE 升压*/
    gpio_set_pin_output(ES_SDB_POWER_IO);
    gpio_write_pin_low(ES_SDB_POWER_IO);

    /* 输出唤醒IO输出低电平*/
    gpio_set_pin_output(ES_WUKEUP_IO);
    gpio_write_pin_low(ES_WUKEUP_IO);
}

void User_Wakeup(void) {
    /* 输出唤醒IO高电平*/
    gpio_set_pin_output(ES_WUKEUP_IO);
    gpio_write_pin_high(ES_WUKEUP_IO);
}

//WAKEUP_IRQHandler
OSAL_IRQ_HANDLER(Vector4C)
{
    md_syscfg_clear_flag_wakeup(SYSCFG);
    md_exti_clear_it_wakeup(EXTI);         // 清除唤醒标志
}

//EXTI_0to1_IRQHandler
OSAL_IRQ_HANDLER(Vector54)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = EXTI->IFM;
    EXTI->ICR = irq_ifm;

    OSAL_IRQ_EPILOGUE();
}

//EXTI_2to3_IRQHandler
OSAL_IRQ_HANDLER(Vector58)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = EXTI->IFM;
    EXTI->ICR = irq_ifm;

    OSAL_IRQ_EPILOGUE();
}

//GP32C4T1_IRQHandler
OSAL_IRQ_HANDLER(Vector7C)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = GP32C4T1->IFM;
    GP32C4T1->ICR = irq_ifm;

    OSAL_IRQ_EPILOGUE();
}

//GP16C4T1_IRQHandler
OSAL_IRQ_HANDLER(Vector80)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = GP16C4T1->IFM;
    GP16C4T1->ICR = irq_ifm;

    OSAL_IRQ_EPILOGUE();
}

//GP16C4T2_IRQHandler
OSAL_IRQ_HANDLER(Vector84)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = GP16C4T2->IFM;
    GP16C4T2->ICR = irq_ifm;

    OSAL_IRQ_EPILOGUE();
}

void Board_Wakeup_Init(void) {
    /*Using USB_SOF to calibrate the internal clock*/
    md_rcu_enable_csu(RCU);
    CSU->CON |= CSU_CON_AUTOEN_MSK;
    CSU->CON |= CSU_CON_CNTEN_MSK;

    es_ble_spi_init();          //SPI

    User_Adc_Init();            //ADC

    rgb_matrix_driver_init();   //PWM DMA 初始化

    Init_Gpio_Infomation();     //GPIO

    User_Systime_Init();        //time定时器

    if (Keyboard_Info.Key_Mode == QMK_USB_MODE) {
        User_Usb_Init();        //USB 插件
    } else {
        Usb_Disconnect();
    }

    Init_Spi_Power_Up = true;
    Init_Spi_100ms_Delay = 0;
    Spi_Interval = SPI_DELAY_RF_TIME;

	NVIC_SetPriority(PendSV_IRQn, 3);
	NVIC_SetPriority(SysTick_IRQn, 3);

    Keyboard_Status.System_Work_Status = 0;
    Keyboard_Status.System_Sleep_Mode = 0;
    Usb_Change_Mode_Wakeup = false;

    Init_Batt_Infomation();

    Led_Power_Up = false;
    Emi_Test_Start = false;

#if LOGO_LED_ENABLE
    Logo_Init();
#endif

#if SIDE_LED_ENABLE
    Side_Init();
#endif
}

void es_chibios_user_idle_loop_hook(void) {
    uint32_t i;

	if(Keyboard_Info.Key_Mode == QMK_USB_MODE) {
        if (Usb_Dis_Connect) {
            Usb_Dis_Connect = false;

            if((g_usb_sof_frame_id != g_usb_sof_frame_id_last) || (Usb_Change_Mode_Wakeup == false)) { //正常通信
                g_usb_sof_frame_id_last = g_usb_sof_frame_id;
                Usb_Suspend_Delay = 0;
                return;
            } else {
                Usb_If_Ok_Led = false;
                Usb_Suspend_Delay++;
			    if (Usb_Suspend_Delay < 800) {        //8S
                    return;
			    }
			    Usb_Suspend_Delay = 0;

                while ((DMA1->CHENSET) & 0x4);

                User_Sleep();
                uint32_t delay = 0;
                while (SPI_IDLE != Spi_Ack_Send_Commad(USER_KEYBOARD_SLEEP)) {
                    delay++;
                    if(delay >= 3600) {
                        delay = 0;
                        User_Wakeup();
                        Usb_Suspend_Delay = 6000;
                        return;
                    }
                }

                delay = 0;
                while (Spi_Send_Recv_Flg) {
                    delay++;
                    if(delay >= 36000) {
                        delay = 0;
                        User_Wakeup();
                        return;
                    }
                }
            }
        } else {
            return;
        }
	} else {
	    if(!Keyboard_Status.System_Sleep_Mode) {    //无线休眠
		    return;
	    }
    }

	/*等待SPI数据发送完成*/
	if(Spi_Send_Recv_Flg) {
		return;
	}

    /*680进入休眠之后，1.2ms 之后 ACK_IO 会高电平，说明休眠完成*/
    uint32_t delay = 0;
    while (!gpio_read_pin(ES_SPI_ACK_IO)) {
        wait_ms(1);
        delay++;
        if(delay >= 100) {
            delay = 0;
            return;
        }
    }

    gpio_set_pin_input_high(ES_SPI_ACK_IO);     //ACK_IO

    md_tick_disable_csr_tickie(TICK);
    NVIC_DisableIRQ((IRQn_Type) SysTick_IRQn);

    User_Systime_Deinit();      //time定时器

    es_ble_spi_deinit();        //SPI

    User_Pwm_Deinit();          //PWM DMA

    User_Usb_Deinit();          //usb插件

    User_Adc_Deinit();          //ADC

    Save_Flash = false;
    Save_Flash_3S_Count = 0;
    Usb_Change_Mode_Wakeup = false;
    Usb_Change_Mode_Delay = 0;
    Led_Power_Up = false;

    ioline_t User_Pin_Tab_Col[KEYBAORD_COL] = MATRIX_USER_COL_PINS;
    ioline_t User_Pin_Tab_Rol[KEYBAORD_ROL] = MATRIX_USER_ROW_PINS;
	//唤醒源配置
    for(i = 0; i < KEYBAORD_COL; i++) { //COL
        gpio_set_pin_output(User_Pin_Tab_Col[i]);
        gpio_write_pin_low(User_Pin_Tab_Col[i]);
    }

    for(i = 0; i < KEYBAORD_ROL; i++) { //ROL
        gpio_set_pin_input_high(User_Pin_Tab_Rol[i]);
    }
    //波动开关
    gpio_set_pin_input_high(MODE_2P4G_IO);                    //B12
    gpio_set_pin_input_high(MODE_BLE_IO);                     //B13
	gpio_set_pin_input_high(MAC_WIN_IO);                      //B14

    /*未插入USB线时候，插入USB唤醒*/
    gpio_set_pin_input(ES_USB_POWER_IO);

    //滚轮
    gpio_set_pin_input_high(WHEEL_ZA_IO);        //ZA
    gpio_set_pin_input_high(WHEEL_ZB_IO);        //ZB
	
    /*默认 B0 B3 B4 B5 B6 B7*/
    uint32_t Gpio_Enable = 0X000000F9;
    uint32_t Gpio_Status_H = 0X00000000;
    uint32_t Gpio_Status_L = 0X000000F9;

    if (gpio_read_pin(ES_USB_POWER_IO)) {   //USB
        Gpio_Status_L |= 0X20;
    } else {
        Gpio_Status_H |= 0X20;
    }
    Gpio_Enable |= 0X20;

    if (gpio_read_pin(WHEEL_ZA_IO)) {       //ZA
        Gpio_Status_L |= 0X04;
    } else {
        Gpio_Status_H |= 0X04;
    }
    Gpio_Enable |= 0X04;

    if (gpio_read_pin(WHEEL_ZB_IO)) {       //ZB
        Gpio_Status_L |= 0X400;
    } else {
        Gpio_Status_H |= 0X400;
    }
    Gpio_Enable |= 0X400;

    if (gpio_read_pin(MODE_2P4G_IO)) {      //B12
        Gpio_Status_L |= 0X1000;
    } else {
        Gpio_Status_H |= 0X1000;
    }
    Gpio_Enable |= 0X1000;

    if (gpio_read_pin(MODE_BLE_IO)) {       //B13
        Gpio_Status_L |= 0X2000;
    } else {
        Gpio_Status_H |= 0X2000;
    }
    Gpio_Enable |= 0X2000;

    if (gpio_read_pin(MAC_WIN_IO)) {        //B14
        Gpio_Status_L |= 0X4000;
    } else {
        Gpio_Status_H |= 0X4000;
    }
    Gpio_Enable |= 0X4000;

    //GP16C4T2_CH2 PB5
    /*PB5 和 PC5 冲突只能用一个*/
    GPIOB->MOD &= 0xFFFFF3FF;   //选择复用模式 GP16C4T2_CH2
    GPIOB->MOD |= 0x00000800;   //选择复用模式 NABLE:1 DISABLE:0

    GPIOB->AFL &= 0xFF0FFFFF;   //选择复用功能
    GPIOB->AFL |= 0x00300000;   //选择复用模式 NABLE:1 DISABLE:0

    md_exti_set_interrupt_pin_0_7(EXTI, MD_EXTI_GPIOB0 | MD_EXTI_GPIOB2 | MD_EXTI_GPIOB3 | MD_EXTI_GPIOB4 | MD_EXTI_GPIOC5 | MD_EXTI_GPIOB6 | MD_EXTI_GPIOB7);
    md_exti_set_interrupt_pin_8_15(EXTI, MD_EXTI_GPIOB10 | MD_EXTI_GPIOB12 | MD_EXTI_GPIOB13 | MD_EXTI_GPIOB14);

    md_exti_enable_it_gpio_pin(EXTI, Gpio_Enable);	                            /*0~7 , 10   外部中断使能*/
    md_exti_enable_rising_edge_trigger(EXTI, Gpio_Status_H);                    /*0~7 , 10   检测到上升沿（rising edge）时触发中断。*/
    md_exti_enable_falling_edge_trigger(EXTI, Gpio_Status_L);                   /*0~7 , 10   检测到下降沿（falling edge）时触发中断。*/

    NVIC_EnableIRQ((IRQn_Type) EXTI_0to1_IRQn); 	                            /* EXTI_0to1_IRQn interrupt */
    NVIC_EnableIRQ((IRQn_Type) EXTI_2to3_IRQn); 	                            /* EXTI_2to3_IRQn interrupt */
    NVIC_EnableIRQ((IRQn_Type) EXTI_4to15_IRQn);	                            /* EXTI_4to15_IRQn interrupt */

    //GP16C4T2_CH2 PB5
    md_rcu_enable_gp16c4t2(RCU);
    md_timer_set_prescaler_value_pscv(GP16C4T2, 1);								//分频系数
    md_timer_set_auto_reload_value_arrv(GP16C4T2, 0xffff);						//计数最大值
    md_timer_set_cc2_func_cc2ssel(GP16C4T2, MD_TIMER_CHMODE_INPUT_DIRECT);		//使用当前通道
    md_timer_set_cc2_input_edge_cc2pol(GP16C4T2, MD_TIMER_OUTPUTPOLARITY_LOW);	//捕捉极性
    md_timer_enable_cc2_output_cc2en(GP16C4T2);									//通道使能
    md_timer_enable_counter_cnten(GP16C4T2);									//定时器使能
    md_timer_enable_it_ch2(GP16C4T2);                                           //通道中断使能
    NVIC_EnableIRQ((IRQn_Type) GP16C4T2_IRQn);                                  /* GP16C4T2_IRQHandler */
	md_rcu_enable_gp16c4t2_in_sleep_mode(RCU);                                  /*保持休眠下工作*/

    uint8_t Usb_Sleep_Status = 0XAA;
    if (!gpio_read_pin(ES_USB_POWER_IO) && (Keyboard_Info.Key_Mode == QMK_USB_MODE)) {
        NVIC_DisableIRQ((IRQn_Type) USB_IRQn);          /* USB_IRQHandler */
        Usb_Sleep_Status = 0XFF;
    }

	//进入低功耗
    SCB->SCR &= ~(1UL << 2);    // SCR[2] = 0 (SLEEP)

    md_rcu_set_system_clock_source(RCU, MD_RCU_SW_SYSCLK_HRC);
    md_rcu_disable_pll0(RCU);

    if(Keyboard_Info.Key_Mode != QMK_USB_MODE) {
        md_rcu_disable_usb(RCU);
        md_rcu_disable_hrc48(RCU);

        __WFI();                //Wait For Interrupt

        /*唤醒*/
        md_rcu_enable_hrc48(RCU);
        for(i = 0;i < 99999;) {
            if(md_rcu_is_active_flag_hrc48_ready(RCU) == MD_RCU_HRC48RDY_READY)
                break;
            i++;
        }
        md_rcu_enable_usb(RCU);
    } else {                    //在USB模式下
        md_rcu_enable_usb_in_sleep_mode(RCU);
        __WFI();                //Wait For Interrupt
    }

    md_rcu_set_system_clock_source(RCU, MD_RCU_SW_SYSCLK_HRC48);

    if ((Keyboard_Info.Key_Mode == QMK_USB_MODE) && (Usb_Sleep_Status == 0XFF)) {
        NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
        Usb_Sleep_Status = 0XAA;
    }

    /*休眠唤醒之后记录唤醒按下按键的位置*/
    uint8_t Sleep_Status = 0x00;
    for(i = 0; i < KEYBAORD_ROL; i++) { //ROL
        if (!gpio_read_pin(User_Pin_Tab_Rol[i])) {
            Sleep_Status |= (1 << i);
        }
    }

    NVIC_DisableIRQ((IRQn_Type) EXTI_0to1_IRQn);    /* EXTI_0to1_IRQn interrupt */
    NVIC_DisableIRQ((IRQn_Type) EXTI_2to3_IRQn);    /* EXTI_2to3_IRQn interrupt */
    NVIC_DisableIRQ((IRQn_Type) EXTI_4to15_IRQn);   /* EXTI_4to15_IRQn interrupt */
    NVIC_DisableIRQ((IRQn_Type) GP16C4T2_IRQn);     /* GP16C4T2_IRQHandler */

	//唤醒源配置输出高电平
    for(i = 0; i < KEYBAORD_COL; i++) { //COL
        gpio_write_pin_high(User_Pin_Tab_Col[i]);
    }

    delay = 50;
    while(delay--);

    uint8_t Rol_Count = 0,Col_Count = 0;
    for (i = 0; i < KEYBAORD_ROL; i++) {
        if ((1 << i) & Sleep_Status) {
            for(uint8_t j = 0; j < KEYBAORD_COL; j++) {
                gpio_write_pin_low(User_Pin_Tab_Col[j]);

                delay = 50;
                while(delay--);

                if (!gpio_read_pin(User_Pin_Tab_Rol[i])) {
                    Rol_Count = i;
                    Col_Count = j;
                    break;
                }

                for(uint8_t k = 0; k < KEYBAORD_COL; k++) {
                    gpio_write_pin_high(User_Pin_Tab_Col[j]);
                }

                delay = 50;
                while(delay--);
            }
        }
    }

	//唤醒源配置输出高电平
    for(i = 0; i < KEYBAORD_COL; i++) { //COL
        gpio_write_pin_high(User_Pin_Tab_Col[i]);
    }

    gpio_set_pin_input_low(ES_SPI_ACK_IO);     //ACK_IO

    md_tick_enable_csr_tickie(TICK);
	NVIC_EnableIRQ((IRQn_Type) SysTick_IRQn);

	//在USB模式下
    if(Keyboard_Info.Key_Mode == QMK_USB_MODE) {
        if (USBD1.status & 0x2) {
            usb_lld_wakeup_host(0);

            uint16_t cnt = 200;
			while(cnt--) {
                if(USBD1.state != USB_ACTIVE) {
                    wait_ms(10);
                }
			}
        }

        register_code(dynamic_keymap_get_keycode(0, Rol_Count, Col_Count));
        wait_ms(2);
        unregister_code(dynamic_keymap_get_keycode(0, Rol_Count, Col_Count));
        wait_ms(2);
    }

	Board_Wakeup_Init();
}
/*********************************************************/

/**********************系统函数***************************/
/*  键盘扫描按键延时 */
void matrix_io_delay(void) {
}

void matrix_output_select_delay(void) {
}

void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
}

void housekeeping_task_user(void) {
    es_chibios_user_idle_loop_hook();
    if(User_EE_CLR_Start_Flag){                 //长按3s重启按键
        User_EE_CLR_Start_Flag = false;

        Keyboard_Info.Led_On_Off = INIT_LED_ON_OFF;
        Keyboard_Info.Nkro = INIT_ALL_KEY;
        Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
        Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
    #if LOGO_LED_ENABLE
        Keyboard_Info.Logo_On_Off = INIT_LOGO_ON_OFF;
        Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
        Keyboard_Info.Logo_Colour = INIT_LOGO_COLOUR;
        Keyboard_Info.Logo_Saturation = INIT_LOGO_SATURATION;
        Keyboard_Info.Logo_Brightness = INIT_LOGO_BRIGHTNESS;
        Keyboard_Info.Logo_Speed = INIT_LOGO_SPEED;
        Logo_Init();
    #endif
    #if SIDE_LED_ENABLE
        Keyboard_Info.Side_On_Off = INIT_SIDE_ON_OFF;
        Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
        Keyboard_Info.Side_Colour = INIT_SIDE_COLOUR;
        Keyboard_Info.Side_Saturation = INIT_SIDE_SATURATION;
        Keyboard_Info.Side_Brightness = INIT_SIDE_BRIGHTNESS;
        Keyboard_Info.Side_Speed = INIT_SIDE_SPEED;
        Side_Init();
    #endif
        Reset_Save_Flash = true;
        /*将当前模式写入flash*/
        eeprom_write_block_user((void *)&Keyboard_Info.Key_Mode, 0, sizeof(Keyboard_Info_t));
        Reset_Save_Flash = false;

    #ifdef NO_RESET
        eeconfig_init();
    #else
        eeconfig_disable();
        soft_reset_keyboard();
    #endif

        return;
    }
}
/*********************************************************/

//DMA1_CH12_IRQHandler  DMA中断
OSAL_IRQ_HANDLER(Vector68)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = DMA1->IFM;
    DMA1->ICR = irq_ifm;

    if(irq_ifm & (1U << 1)){
        /*DMA 收发完成*/
    }

    OSAL_IRQ_EPILOGUE();
}

//EXTI_4to15_IRQHandler IO中断
OSAL_IRQ_HANDLER(Vector5C)
{
    uint32_t irq_ifm;
    OSAL_IRQ_PROLOGUE();

    irq_ifm = EXTI->IFM;
    EXTI->ICR = irq_ifm;

    if (!Init_Spi_Power_Up) {
        if(irq_ifm & (1U << 4)) {                                                       /*当IO PA4检测到下降沿会产生中断*/
            if (Spi_Send_Recv_Flg) {
                if (Send_Key_Type == SPI_NACK) {
                    if (!gpio_read_pin(ES_SPI_ACK_IO)) {                                //下降沿中断
                        Spi_Send_Recv_Flg = 0;
                    }
                } else {
                    if (gpio_read_pin(ES_SPI_ACK_IO)) {                                 //上升沿中断
                        if (Spi_Send_Recv_Flg == 1) {                                   /*立即发送一包64字节的空包，并且获取680返回的数据*/
                            Spi_Send_Recv_Flg = 2;
                            memset((void *)g_es_spi_rx_buf, 0x00, USER_KEYBOARD_LENGTH);
                            es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, (void*)(0x1000));
                        }
                    } else {                                                            //下降沿中断
                        if (Spi_Send_Recv_Flg == 2) {                                   //说明发送完成收到ACK，DMA发送接收完成
                            if (Emi_Test_Start && ((USER_EMI_COMMAND == g_es_spi_rx_buf[0]) || ((USER_EMI_COMMAND & 0X7F) == g_es_spi_rx_buf[0]))) {
                                Get_Spi_Return_Data(g_es_spi_rx_buf);                   //获取返回值
                                Spi_Send_Recv_Flg = 0;
                            } else if (USER_KEYBOARD_COMMAND == g_es_spi_rx_buf[0]) {   //如果这一包的ACK接收无误则可发送下一包数据，否则继续发送上一包数据
                                Get_Spi_Return_Data(g_es_spi_rx_buf);                   //获取返回值
                                Spi_Send_Recv_Flg = 0;
                            } else {
                                Repet_Send_Count++;
                                if (Repet_Send_Count >= 3) {                            //如果重复发送三包之后数据都不对则不再重发
                                    Repet_Send_Count = 0;
                                    Spi_Send_Recv_Flg = 0;
                                } else {
                                    Spi_Send_Recv_Flg = 1;
                                    es_spi_send_recv_by_dma(USER_KEYBOARD_LENGTH, g_es_spi_rx_buf, g_es_spi_tx_buf);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    OSAL_IRQ_EPILOGUE();
}

void User_Adc_Batt_Power_Up_Init(void) {
    uint8_t Min_Batt = 0, Max_Batt = 0;
    for (uint8_t i = 0; i < USER_BATT_POWER_SCAN_COUNT; i++) {  /*取出最小值 最大值*/
        if (User_Scan_Batt[Min_Batt] < User_Scan_Batt[i]) {
            Min_Batt = i;
        }

        if (User_Scan_Batt[Max_Batt] > User_Scan_Batt[i]) {
            Max_Batt = i;
        }
    }

    /*求平均数*/
    uint16_t Temp_Batt_Sub = 0;
    if (Min_Batt == Max_Batt) {                 //去掉最大、最小值
        for (uint8_t i = 0; i < (USER_BATT_POWER_SCAN_COUNT - 2); i++) {
            Temp_Batt_Sub += User_Scan_Batt[i];
        }
    } else {
        for (uint8_t i = 0; i < USER_BATT_POWER_SCAN_COUNT; i++) {
            if ((Min_Batt == i) || (Max_Batt == i)) {
                continue;                       //跳过最大最小值
            }
            Temp_Batt_Sub += User_Scan_Batt[i];
        }
    }

    /*当前实际电压*/
    uint16_t Temp_Average = (Temp_Batt_Sub / (USER_BATT_POWER_SCAN_COUNT - 2));

    uint8_t Temp_Batt_Number = 0;
    if (Temp_Average >= USER_BATT_HIGH_POWER) {
        Temp_Batt_Number = 100;
    } else if (Temp_Average <= USER_BATT_STDOWN_POWER) {
        Temp_Batt_Number = 0;
    } else {
        Temp_Batt_Number = (((Temp_Average - USER_BATT_STDOWN_POWER) * 100) / (USER_BATT_HIGH_POWER - USER_BATT_STDOWN_POWER));//实际剩余电池电压占比
    }

    if (Temp_Average <= USER_BATT_STDOWN_POWER) {       //关机
        User_Power_Low_Count++;
        if (User_Power_Low_Count >= 4) {
            User_Power_Low_Count = 0;
            User_Power_Low = true;
        }
    } else if (Temp_Average <= USER_BATT_LOW_POWER) {   //低电，关灯
        User_Power_Low_Count++;
        if (User_Power_Low_Count >= 10) {
            User_Power_Low_Count = 0;
            User_Power_Low = true;
        }
    } else {                                            //正常情况下清除低电计数
        User_Power_Low_Count = 0;
    }

    User_Batt_BaiFen = Temp_Batt_Number;
    User_Batt_Old_BaiFen = User_Batt_BaiFen;            //覆盖旧的电池电量百分比

    if (User_Batt_BaiFen != Keyboard_Info.Batt_Number) {
        Keyboard_Info.Batt_Number = User_Batt_BaiFen;
        Save_Flash_Set();                               //实时更新Flsh中的电池电量
    }

    User_Adc_Batt_Count = 0;
    User_Batt_10ms_Count = 0;
    User_Batt_Time_15S_Count = 0;
    User_Batt_Power_Up = false;
}

void User_Adc_Batt_Number(void) {
    if (es_stdby_pin_state == 2) {          //充满
        User_Batt_BaiFen = 100;
        User_Batt_Old_BaiFen = 100;
        if (Keyboard_Info.Batt_Number != User_Batt_BaiFen) {
            Keyboard_Info.Batt_Number = User_Batt_BaiFen;
            User_Batt_Send_Spi = true;
            Save_Flash_Set();                            //实时更新Flsh中的电池电量
        }
        User_Power_Low = false;
        User_Power_Low_Count = 0;
        return;
    }

    uint8_t Min_Batt = 0, Max_Batt = 0;
    for (uint8_t i = 0; i < USER_BATT_SCAN_COUNT; i++) {  /*取出最小值 最大值*/
        if (User_Scan_Batt[Min_Batt] < User_Scan_Batt[i]) {
            Min_Batt = i;
        }

        if (User_Scan_Batt[Max_Batt] > User_Scan_Batt[i]) {
            Max_Batt = i;
        }
    }

    /*求平均数*/
    uint16_t Temp_Batt_Sub = 0;
    if (Min_Batt == Max_Batt) {
        for (uint8_t i = 0; i < (USER_BATT_SCAN_COUNT - 2); i++) {
            Temp_Batt_Sub += User_Scan_Batt[i];
        }
    } else {
        for (uint8_t i = 0; i < USER_BATT_SCAN_COUNT; i++) {
            if ((Min_Batt == i) || (Max_Batt == i)) {
                continue;
            }
            Temp_Batt_Sub += User_Scan_Batt[i];
        }
    }

    /*当前实际电压*/
    uint16_t Temp_Average = (Temp_Batt_Sub / (USER_BATT_SCAN_COUNT - 2));

    uint8_t Temp_Batt_Number = 0;
    if (Temp_Average >= USER_BATT_HIGH_POWER) {
        Temp_Batt_Number = 100;
    } else if (Temp_Average <= USER_BATT_STDOWN_POWER) {
        Temp_Batt_Number = 0;
    } else {
        Temp_Batt_Number = (((Temp_Average - USER_BATT_STDOWN_POWER) * 100) / (USER_BATT_HIGH_POWER - USER_BATT_STDOWN_POWER));
    }

    if (es_stdby_pin_state == 1) {   //充电
        if (Temp_Batt_Number >= 100) {
            Temp_Batt_Number = 99;
        } else if (Temp_Batt_Number <= 0) {
            Temp_Batt_Number = 1;
        }
    } else {                                                //未充电
        if (Temp_Average <= USER_BATT_STDOWN_POWER) {       //关机
            User_Power_Low_Count++;
            if (User_Power_Low_Count >= 5) {
                User_Power_Low_Count = 0;
                User_Power_Low = true;
            }
        } else if (Temp_Average <= USER_BATT_LOW_POWER) {   //低电，关灯
            User_Power_Low_Count++;
            if (User_Power_Low_Count >= 10) {
                User_Power_Low_Count = 0;
                User_Power_Low = true;
            }
        } else {                                            //正常情况下清除低电计数
            User_Power_Low_Count = 0;
        }
    }

    if (es_stdby_pin_state) {   //充电
        if (Temp_Batt_Number > User_Batt_Old_BaiFen) {  //电量 + 1
            if (User_Batt_Time_15S_Count >= USER_BATT_DELAY_TIME) {
                User_Batt_Time_15S_Count = 0;
                if (User_Batt_BaiFen <= 98) {
                    User_Batt_BaiFen++;
                }
                User_Batt_Old_BaiFen = User_Batt_BaiFen;
            }
        } else {
            User_Batt_Time_15S_Count = 0;
        }
        User_Power_Low = false;
        User_Power_Low_Count = 0;
    } else {                    //未充电
        if (Temp_Batt_Number < User_Batt_Old_BaiFen) {
            if (User_Batt_Time_15S_Count >= USER_BATT_DELAY_TIME) {   //电量 - 1
                User_Batt_Time_15S_Count = 0;
                if (User_Batt_BaiFen) {
                    User_Batt_BaiFen--;
                }
                User_Batt_Old_BaiFen = User_Batt_BaiFen;
            }
        } else {
            User_Batt_Time_15S_Count = 0;
        }
    }

    if (Keyboard_Info.Batt_Number != User_Batt_BaiFen) {
        Keyboard_Info.Batt_Number = User_Batt_BaiFen;
        User_Batt_Send_Spi = true;
        Save_Flash_Set();
    }
}

void Init_Keyboard_Infomation(void){
    /*上电将flash里面的工作模式读取出来*/
    eeprom_read_block_user((void *)&Keyboard_Info, 0, sizeof(Keyboard_Info_t));

    /*如果 eeprom 里面是空数据直接初始化结构体*/
    if ((Keyboard_Info.Key_Mode == 0XFF) && (Keyboard_Info.Ble_Channel == 0XFF) && (Keyboard_Info.Batt_Number == 0XFF)  && (Keyboard_Info.Nkro == 0XFF) && (Keyboard_Info.Mac_Win_Mode == 0XFF) && (Keyboard_Info.Win_Lock == 0XFF) && (Keyboard_Info.Led_On_Off == 0XFF)) {
        Keyboard_Info.Key_Mode = INIT_WORK_MODE;
        Keyboard_Info.Ble_Channel = INIT_BLE_CHANNEL;
        Keyboard_Info.Batt_Number = INIT_BATT_NUMBER;
        Keyboard_Info.Nkro = INIT_ALL_KEY;
        Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
        Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
        Keyboard_Info.Led_On_Off = INIT_LED_ON_OFF;
    #if LOGO_LED_ENABLE
        Keyboard_Info.Logo_On_Off = INIT_LOGO_ON_OFF;
        Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
        Keyboard_Info.Logo_Colour = INIT_LOGO_COLOUR;
        Keyboard_Info.Logo_Saturation = INIT_LOGO_SATURATION;
        Keyboard_Info.Logo_Brightness = INIT_LOGO_BRIGHTNESS;
        Keyboard_Info.Logo_Speed = INIT_LOGO_SPEED;
    #endif
    #if SIDE_LED_ENABLE
        Keyboard_Info.Side_On_Off = INIT_SIDE_ON_OFF;
        Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
        Keyboard_Info.Side_Colour = INIT_SIDE_COLOUR;
        Keyboard_Info.Side_Saturation = INIT_SIDE_SATURATION;
        Keyboard_Info.Side_Brightness = INIT_SIDE_BRIGHTNESS;
        Keyboard_Info.Side_Speed = INIT_SIDE_SPEED;
    #endif
    } else if ((Keyboard_Info.Key_Mode == 0) && (Keyboard_Info.Ble_Channel == 0) && (Keyboard_Info.Batt_Number == 0)  && (Keyboard_Info.Nkro == 0) && (Keyboard_Info.Mac_Win_Mode == 0) && (Keyboard_Info.Win_Lock == 0) && (Keyboard_Info.Led_On_Off == 0)) {
        Keyboard_Info.Key_Mode = INIT_WORK_MODE;
        Keyboard_Info.Ble_Channel = INIT_BLE_CHANNEL;
        Keyboard_Info.Batt_Number = INIT_BATT_NUMBER;
        Keyboard_Info.Nkro = INIT_ALL_KEY;
        Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
        Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
        Keyboard_Info.Led_On_Off = INIT_LED_ON_OFF;
    #if LOGO_LED_ENABLE
        Keyboard_Info.Logo_On_Off = INIT_LOGO_ON_OFF;
        Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
        Keyboard_Info.Logo_Colour = INIT_LOGO_COLOUR;
        Keyboard_Info.Logo_Saturation = INIT_LOGO_SATURATION;
        Keyboard_Info.Logo_Brightness = INIT_LOGO_BRIGHTNESS;
        Keyboard_Info.Logo_Speed = INIT_LOGO_SPEED;
    #endif
    #if SIDE_LED_ENABLE
        Keyboard_Info.Side_On_Off = INIT_SIDE_ON_OFF;
        Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
        Keyboard_Info.Side_Colour = INIT_SIDE_COLOUR;
        Keyboard_Info.Side_Saturation = INIT_SIDE_SATURATION;
        Keyboard_Info.Side_Brightness = INIT_SIDE_BRIGHTNESS;
        Keyboard_Info.Side_Speed = INIT_SIDE_SPEED;
    #endif
    } else {
        if (Keyboard_Info.Key_Mode > QMK_USB_MODE) {
            Keyboard_Info.Key_Mode = QMK_USB_MODE;
        }

        if (Keyboard_Info.Ble_Channel > QMK_BLE_CHANNEL_3) {
            Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_3;
        }

        if (Keyboard_Info.Batt_Number > 100) {
            Keyboard_Info.Batt_Number = 100;
        }

        if (Keyboard_Info.Nkro > INIT_ALL_KEY) {
            Keyboard_Info.Nkro = INIT_ALL_KEY;
        }

        if (Keyboard_Info.Mac_Win_Mode > INIT_MAC_MODE) {
            Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
        }

        if (Keyboard_Info.Win_Lock > INIT_WIN_LOCK) {
            Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
        }

        if (Keyboard_Info.Led_On_Off > INIT_LED_OFF) {
            Keyboard_Info.Led_On_Off = INIT_LED_ON_OFF;
        }
    #if LOGO_LED_ENABLE
        if (Keyboard_Info.Logo_On_Off > LOGO_LED_OFF) {
            Keyboard_Info.Logo_On_Off = INIT_LOGO_ON_OFF;
        }

        if (Keyboard_Info.Logo_Mode > LOGO_OFF_MODE) {
            Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
        }

        if (Keyboard_Info.Logo_Colour > LOGO_MAX_COLOUR) {
            Keyboard_Info.Logo_Colour = INIT_LOGO_COLOUR;
        }

        if (Keyboard_Info.Logo_Saturation > LOGO_MIN_SATURATION) {
            Keyboard_Info.Logo_Saturation = INIT_LOGO_SATURATION;
        }

        if (Keyboard_Info.Logo_Brightness > LOGO_MAX_BRIGHTNESS) {
            Keyboard_Info.Logo_Brightness = INIT_LOGO_BRIGHTNESS;
        }

        if (Keyboard_Info.Logo_Speed > LOGO_MAX_SPEED) {
            Keyboard_Info.Logo_Speed = INIT_LOGO_SPEED;
        }
    #endif
    #if SIDE_LED_ENABLE
        if (Keyboard_Info.Side_On_Off > SIDE_LED_OFF) {
            Keyboard_Info.Side_On_Off = INIT_SIDE_ON_OFF;
        }

        if (Keyboard_Info.Side_Mode > SIDE_LIGHT_MODE) {
            Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
        }

        if (Keyboard_Info.Side_Colour > SIDE_MAX_COLOUR) {
            Keyboard_Info.Side_Colour = INIT_SIDE_COLOUR;
        }

        if (Keyboard_Info.Side_Saturation > SIDE_MIN_SATURATION) {
            Keyboard_Info.Side_Saturation = INIT_SIDE_SATURATION;
        }

        if (Keyboard_Info.Side_Brightness > SIDE_MAX_BRIGHTNESS) {
            Keyboard_Info.Side_Brightness = INIT_SIDE_BRIGHTNESS;
        }

        if (Keyboard_Info.Side_Speed > SIDE_MAX_SPEED) {
            Keyboard_Info.Side_Speed = INIT_SIDE_SPEED;
        }
    #endif
    }
}

void es_change_qmk_nkro_mode_enable(void) {  //六键、全键无冲
    if(!keymap_config.nkro) {
        clear_keyboard(); // 清除第一个缓冲区以防止卡键
        keymap_config.nkro = true;
        Keyboard_Info.Nkro = keymap_config.nkro;
        Save_Flash_Set();
    }
}

void es_change_qmk_nkro_mode_disable(void) {
    if(keymap_config.nkro) {
        clear_keyboard(); // 清除第一个缓冲区以防止卡键
        keymap_config.nkro = false;

        Keyboard_Info.Nkro = keymap_config.nkro;
        Save_Flash_Set();
    }
}

/*拨动开关*/
void Key_Switch_Mode_Scan(void) {
    Key_Switch_Scan = 0x00;
    if ((gpio_read_pin(MODE_BLE_IO)) && (!gpio_read_pin(MODE_2P4G_IO))) {
        Key_Switch_Scan = 0x01;
    } else if ((!gpio_read_pin(MODE_BLE_IO)) && (gpio_read_pin(MODE_2P4G_IO))) {    // BLE 模式（MODE_BLE_IO 低，MODE_2P4G_IO 高）
        Key_Switch_Scan = 0x02;
    } else if ((gpio_read_pin(MODE_BLE_IO)) && (gpio_read_pin(MODE_2P4G_IO))) {     // USB 模式（两个引脚同时高或者其他状态）
        Key_Switch_Scan = 0x04;
    } else {
        Key_Switch_Scan = 0x04;
    }

    if (gpio_read_pin(MAC_WIN_IO)) {
        Key_Mac_Win_Scan = 0x00;
    } else {
        Key_Mac_Win_Scan = 0xff;
    }

    if (Key_Switch_Scan != Key_Switch_Old) {
        if (Key_Switch_Scan != Key_Switch_Check) {      // 当前模式与上次切换的模式不同
            Key_Switch_delay = 2;                       // 延时防抖
            Key_Switch_Check = Key_Switch_Scan;
        } else {
            if (Key_Switch_delay) {
                Key_Switch_delay--;
            } else {
                Key_Switch_Old = Key_Switch_Scan;

                if (Key_Switch_Check == 0x01) {                     // 2.4G
                    if (Keyboard_Info.Key_Mode != QMK_2P4G_MODE) {
                        Usb_Disconnect();
                        Keyboard_Info.Key_Mode = QMK_2P4G_MODE;
                        Spi_Send_Commad(USER_SWITCH_2P4G_MODE);
                        Save_Flash_Set();                           // 切换模式，保存设置
                        Led_Rf_Pair_Flg = true;                     // 标志位
                    }
                } else if (Key_Switch_Check == 0x02) {              // BLE
                    if (Keyboard_Info.Key_Mode != QMK_BLE_MODE) {
                        Usb_Disconnect();
                        Keyboard_Info.Key_Mode = QMK_BLE_MODE;
                        switch (Keyboard_Info.Ble_Channel) {
                            case QMK_BLE_CHANNEL_1: Spi_Send_Commad(USER_SWITCH_BLE_1_MODE); break;
                            case QMK_BLE_CHANNEL_2: Spi_Send_Commad(USER_SWITCH_BLE_2_MODE); break;
                            case QMK_BLE_CHANNEL_3: Spi_Send_Commad(USER_SWITCH_BLE_3_MODE); break;
                            default:                                                         break;
                        }
                        Save_Flash_Set();
                        Led_Rf_Pair_Flg = true;
                    }
                } else {                                            // USB
                    if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {
                        Keyboard_Info.Key_Mode = QMK_USB_MODE;
                        Usb_If_Ok = true;
                        Spi_Send_Commad(USER_SWITCH_USB_MODE);
                        es_restart_usb_driver();
                        Save_Flash_Set();
                        Led_Rf_Pair_Flg = false;
                    }
                }
            }
        }
    }

    if (Key_Mac_Win_Scan != Key_Mac_Win_Old) {
        if (Key_Mac_Win_Scan != Key_Mac_Win_Check) {
            Key_Mac_Win_delay = 2;
            Key_Mac_Win_Check = Key_Mac_Win_Scan;
        } else {
            if (Key_Mac_Win_delay) {
                Key_Mac_Win_delay--;
            } else {
                Key_Mac_Win_Old = Key_Mac_Win_Scan;

                if (Key_Mac_Win_Check) {    //MAC
                    if (Keyboard_Info.Mac_Win_Mode != INIT_MAC_MODE) {
                        Keyboard_Info.Mac_Win_Mode = INIT_MAC_MODE;
                        Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
                        Mac_Win_Point_Count = 3;
                        unregister_code(KC_LALT); unregister_code(KC_LGUI); unregister_code(KC_RALT); unregister_code(KC_RGUI); unregister_code(KC_APP);
                        Save_Flash_Set();
                        uint8_t current_layer = get_highest_layer(layer_state);
                        if (current_layer != 1) {
                            layer_move(1);
                        }
                        es_change_qmk_nkro_mode_disable();
                    }
                } else {                    //WIN
                    if (Keyboard_Info.Mac_Win_Mode != INIT_WIN_MODE) {
                        Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
                        Mac_Win_Point_Count = 1;
                        unregister_code(KC_LALT); unregister_code(KC_LGUI); unregister_code(KC_RALT); unregister_code(KC_RGUI); unregister_code(KC_APP);
                        Save_Flash_Set();
                        if (!keymap_config.nkro) {
                            es_change_qmk_nkro_mode_enable();
                        }
                        uint8_t current_layer = get_highest_layer(layer_state);
                        if (current_layer != 0) {
                            layer_move(0);
                        }
                    }
                }
            }
        }
    }
}

void Mode_Synchronization(void) {
    switch(Keyboard_Info.Key_Mode) {
        case QMK_BLE_MODE: {
            switch (Keyboard_Info.Ble_Channel) {
                case QMK_BLE_CHANNEL_1: Spi_Send_Commad(USER_SWITCH_BLE_1_MODE);    break;
                case QMK_BLE_CHANNEL_2: Spi_Send_Commad(USER_SWITCH_BLE_2_MODE);    break;
                case QMK_BLE_CHANNEL_3: Spi_Send_Commad(USER_SWITCH_BLE_3_MODE);    break;
                default:                                                            break;
            }
            break;
        }
        case QMK_2P4G_MODE:             Spi_Send_Commad(USER_SWITCH_2P4G_MODE);     break;
        case QMK_USB_MODE:              Spi_Send_Commad(USER_SWITCH_USB_MODE);      break;
        default:                                                                    break;
    }
}

void Ble_Name_Synchronization(void) {                               //蓝牙回连用户名同步
    switch(Ble_Name_Spi_Count) {
        case QMK_BLE_CHANNEL_1:         Spi_Send_Commad(USER_BLE1_WRITE_NAME);      Ble_Name_Spi_Count++;   break;
        case QMK_BLE_CHANNEL_2:         Spi_Send_Commad(USER_BLE2_WRITE_NAME);      Ble_Name_Spi_Count++;   break;
        case QMK_BLE_CHANNEL_3:         Spi_Send_Commad(USER_BLE3_WRITE_NAME);      Ble_Name_Spi_Count++;   break;
        default:                                                                                            break;
    }

    if(Ble_Name_Spi_Count >  QMK_BLE_CHANNEL_3) {
        Ble_Name_Spi_Count = QMK_BLE_CHANNEL_1;
        Ble_Name_Spi_Send = false;
    }
}

/*BS16T1_IRQHandler 2ms定时器*/
OSAL_IRQ_HANDLER(Vector78)
{
    OSAL_IRQ_PROLOGUE();

    BS16T1->ICR = BS16T1->IFM;

    if (Init_Spi_Power_Up) {
        Init_Spi_100ms_Delay++;
        if (Init_Spi_100ms_Delay >= 10) {
            Init_Spi_100ms_Delay = 0;
            if (!gpio_read_pin(ES_SPI_ACK_IO)) {    //低电平说明SPI准备好了
                Init_Spi_Power_Up = false;
            } else {
                Init_Spi_100ms_Delay = 5;           //若SPI未准备好则在等待10ms
            }
        }
    }

    /*无线发码*/
    if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {   //2ms
        if (Keyboard_Status.System_Work_Status && (!Keyboard_Status.System_Sleep_Mode)) {   //休眠指令
            Spi_Ack_Send_Commad(USER_KEYBOARD_SLEEP);
        } else {
            Spi_Main_Loop();
        }
    }

    if (User_Batt_Power_Up_Delay) {                                         //初始化ADC之后延迟100ms再去采集电量
        User_Batt_Power_Up_Delay_100ms_Count++;
        if (User_Batt_Power_Up_Delay_100ms_Count >= 50) {
            User_Batt_Power_Up_Delay_100ms_Count = 0;
            User_Batt_Power_Up_Delay = false;
        }
    } else {                                                                //*ADC电量采集*/
        if (User_Batt_Power_Up) {                                           //上电快速采集 10 次
            User_Batt_10ms_Count++;
            if (User_Batt_10ms_Count >= 4) {                                //8ms
                User_Batt_10ms_Count = 0;
                if((md_adc_is_active_flag_normal_status(ADC)) == 0) {                   //*获取ADC数值，并使能下一次采集*/
                    User_Adc_Batt[User_Adc_Batt_Count] = md_adc_get_normal_data(ADC);   //读取实时电池电压
                    md_adc_set_start_normal(ADC, MD_ADC_CON_NSTART_START_REGULAR);
                    User_Adc_Batt_Count++;
                    if (User_Adc_Batt_Count >= USER_BATT_POWER_SCAN_COUNT) {
                        User_Adc_Batt_Count = 0;
                        for(uint8_t i = 0; i < USER_BATT_POWER_SCAN_COUNT; i++) {
                            User_Scan_Batt[i] = User_Adc_Batt[i];                       //将ADC采样的10次电池电压存储进数组User_Scan_Batt[]里
                        }
                        User_Adc_Batt_Power_Up_Init();
                    }
                }
            }
        } else {
            User_Batt_10ms_Count++;
            if (User_Batt_10ms_Count >= 20) {                               //200ms
                User_Batt_10ms_Count = 0;
                if((md_adc_is_active_flag_normal_status(ADC)) == 0) {       //获取ADC数值，并使能下一次采集
                    User_Adc_Batt[User_Adc_Batt_Count] = md_adc_get_normal_data(ADC);
                    md_adc_set_start_normal(ADC, MD_ADC_CON_NSTART_START_REGULAR);
                    User_Adc_Batt_Count++;
                    if (User_Adc_Batt_Count >= USER_BATT_SCAN_COUNT) {
                        User_Adc_Batt_Count = 0;
                        for(uint8_t i = 0; i < USER_BATT_SCAN_COUNT; i++) {
                            User_Scan_Batt[i] = User_Adc_Batt[i];
                        }
                        User_Adc_Batt_Number();
                    }
                }
                User_Batt_Time_15S_Count++;
            }
        }
    }

    Systick_6ms_Count++;
    if (Systick_6ms_Count >= 3) {           //6ms
        Systick_6ms_Count = 0;
        host_driver_t * temp_driver;        //替换接口
        temp_driver = host_get_driver();
        if((temp_driver != (&es_user_driver))&&(temp_driver)) {
            es_qmk_driver = host_get_driver();
            host_set_driver((host_driver_t *)(&es_user_driver));
        }

        if (!Init_Spi_Power_Up) {
            Key_Switch_Mode_Scan(); // 拨动开关轮询
        }
    }

    Systick_10ms_Count++;
    if (Systick_10ms_Count >= 5) {  //10ms
        Systick_10ms_Count = 0;

        if (Mode_Synchronization_Signal) {  //模式同步
            Mode_Synchronization_Signal = false;
            Mode_Synchronization();
        }

        if (Ble_Name_Spi_Send) {            //蓝牙名称同步
            Ble_Name_Synchronization();
        }

        Systick_Led_Count++;
        if (Systick_Led_Count >= 255) {
            Systick_Led_Count = 0;
        }

        Batt_Led_Count++;
        if (Batt_Led_Count >= 255) {
            Batt_Led_Count = 0;
        }

        if (Led_Power_Up == false) {
            Led_Power_Up_Delay++;
            if (Led_Power_Up_Delay >= 50) { //500ms
                Led_Power_Up_Delay = 0;
                Led_Power_Up = true;
                if (Keyboard_Info.Key_Mode == QMK_BLE_MODE) {
                    User_Batt_Send_Spi = true;
                }
            }
        }

    #if LOGO_LED_ENABLE
        Logo_Flash_Count++;
        if (Logo_Flash_Count >= 255) {
            Logo_Flash_Count = 0;
        }

        Logo_Led_Count++;
        if (Logo_Led_Count >= 255) {
            Logo_Led_Count = 0;
        }
    #endif
    #if SIDE_LED_ENABLE
        Side_Led_Count++;
        if (Side_Led_Count >= 255) {
            Side_Led_Count = 0;
        }
    #endif

        Usb_Change_Mode_Delay++;
        if (Usb_Change_Mode_Delay >= USER_TIME_3S_TIME) { //3S
            Usb_Change_Mode_Delay = 0;
            Usb_Change_Mode_Wakeup = true;
        }

        if (Save_Flash) {
            Save_Flash_3S_Count++;
            if (Save_Flash_3S_Count >= USER_TIME_3S_TIME) { //3S
                if (Spi_Send_Recv_Flg || (gpio_read_pin(ES_SPI_ACK_IO)) || (!Led_Flash_Busy)) {  // SPI通讯的过程中不写Flash
                    Save_Flash_3S_Count = (USER_TIME_3S_TIME - 10);
                } else {
                    Reset_Save_Flash = true;
                    eeprom_write_block_user((void *)&Keyboard_Info, 0, sizeof(Keyboard_Info_t)); // 将当前模式写入flash
                    Reset_Save_Flash = false;
                    Save_Flash = false;
                    Save_Flash_3S_Count = 0;
                }
            }
        } else {
            Save_Flash_3S_Count = 0;
        }

        if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {
            if (User_Batt_Send_Spi) {   //上报电池电量
                User_Batt_Send_Spi = false;
                Spi_Send_Commad(USER_BATTERY_DATA);
            }
            Usb_If_Ok = false;
			Usb_If_Ok_Led = false;
        } else {
            if (Usb_If_Ok && (!Led_Point_Count)) {
                Usb_If_Ok_Delay++;
                if (Usb_If_Ok_Delay >= 200) {
                    Usb_If_Ok_Delay = 0;
                    Usb_If_Ok = false;
                }
            }

            g_usb_sof_frame_id = ((USB->FRAME1) | (USB->FRAME2 << 8));
            Usb_Dis_Connect = true;
        }

        /*查询是否有连接USB*/
        if (gpio_read_pin(ES_USB_POWER_IO)) {
            /*获取电池充电状态*/
            if (gpio_read_pin(ES_BATT_STDBY_IO)) {
                es_stdby_pin_state = 1;            //正在充电
                if (!User_Key_Batt_Num_Flag) {
                    User_Key_Batt_Num_Flag = true;
                    User_Key_Batt_LED_Flag = true;
                }
            } else {
                es_stdby_pin_state = 2;             //充满
                if (!User_Key_Batt_Num_Flag) {
                    User_Key_Batt_Num_Flag = true;
                    User_Key_Batt_LED_Flag = true;
                }
            }
        } else {
            es_stdby_pin_state = 0;                 //未充电
            User_Key_Batt_Num_Flag = false;
            User_Key_Batt_Count = 0;
        }

        if (User_Key_Batt_LED_Flag) {
            User_Key_Batt_Count++;
            if (User_Key_Batt_Count >= USER_TIME_10S_TIME) {
                User_Key_Batt_LED_Flag = false;
                User_Key_Batt_Count = 0;
            } 
        }


        Time_3s_Count++;
        if (Time_3s_Count >= USER_TIME_3S_TIME) {   //3S
            Time_3s_Count = 0;

            if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {   //长按3S配对
                if (Key_2p4g_Status || Key_Ble_1_Status || Key_Ble_2_Status || Key_Ble_3_Status) {  //长按3s强制配对
                    switch (Keyboard_Info.Key_Mode) {
                        case QMK_2P4G_MODE: {
                            if (Key_2p4g_Status){       
                                Key_2p4g_Status = 0;
                                Spi_Send_Commad(USER_SWITCH_2P4G_PAIR);
                                Led_Rf_Pair_Flg = true;
                            }
                            break;
                        }
                        case QMK_BLE_MODE: {
                            if ((Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_1) && Key_Ble_1_Status){
                                Key_Ble_1_Status = 0;
                                Spi_Send_Commad(USER_SWITCH_BLE_1_PAIR);
                                Led_Rf_Pair_Flg = true;
                            } else if ((Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_2) && Key_Ble_2_Status){
                                Key_Ble_2_Status = 0;
                                Spi_Send_Commad(USER_SWITCH_BLE_2_PAIR);
                                Led_Rf_Pair_Flg = true;
                            } else if ((Keyboard_Info.Ble_Channel == QMK_BLE_CHANNEL_3) && Key_Ble_3_Status){
                                Key_Ble_3_Status = 0;
                                Spi_Send_Commad(USER_SWITCH_BLE_3_PAIR);
                                Led_Rf_Pair_Flg = true;
                            }
                            break;
                        }
                        default: {
                            break;
                        }
                    }
                }
            }
        }

        if (User_QMK_EE_CLR_Flag) {        //长按3秒FN+SPACE键盘复位
            Time_3s_EE_CLR_Count++;
            if ((Time_3s_EE_CLR_Count >= USER_TIME_3S_TIME) ) {
                Time_3s_EE_CLR_Count = 0;
                User_QMK_EE_CLR_Flag = false;       // 复位后重置状态
                User_EE_CLR_Start_Flag = true;
            }
        }
    }

    Systick_Interval_Count++;
    if (Systick_Interval_Count >= Spi_Interval) { //120ms
        Systick_Interval_Count = 0;

		if (!Keyboard_Status.System_Work_Status) {
			if(Spi_Ack_Send_Commad(USER_GET_RF_STATUS) == SPI_BUSY) {   //获取无线状态、配对、回连
				Systick_Interval_Count = (Spi_Interval - 10);
			}
		}
    }

    OSAL_IRQ_EPILOGUE();
}

/*拨动开关在波动的瞬间会断电，所以在上电的时候需要特殊处理*/
void Key_Switch_Mode_Power(void) {
    uint8_t Scan_Delay = 0;
    uint8_t Power_Up_Mode = QMK_USB_MODE,Power_Up_Mac_Win;
    for(uint8_t i = 0; i < 5; i++) {
        if ((gpio_read_pin(MODE_BLE_IO)) && (!gpio_read_pin(MODE_2P4G_IO))) {
            Power_Up_Mode = QMK_2P4G_MODE;
        } else if ((!gpio_read_pin(MODE_BLE_IO)) && (gpio_read_pin(MODE_2P4G_IO))) {
            Power_Up_Mode = QMK_BLE_MODE;
        } else if ((gpio_read_pin(MODE_BLE_IO)) && (gpio_read_pin(MODE_2P4G_IO))) {
            Power_Up_Mode = QMK_USB_MODE;
        } else {
            Power_Up_Mode = QMK_USB_MODE;
        }

        if (gpio_read_pin(MAC_WIN_IO)) {
            Power_Up_Mac_Win = INIT_WIN_MODE;
        } else {
            Power_Up_Mac_Win = INIT_MAC_MODE;
        }

        Scan_Delay = 200;
        while(Scan_Delay--);
    }

    if (Power_Up_Mode != Keyboard_Info.Key_Mode) {
        Keyboard_Info.Key_Mode = Power_Up_Mode;
        Save_Flash_Set();
    }

    if (Power_Up_Mac_Win != Keyboard_Info.Mac_Win_Mode) {
        Keyboard_Info.Mac_Win_Mode = Power_Up_Mac_Win;
        Save_Flash_Set();
    }
}

void board_init(void) {
    es_ble_spi_init();          //SPI

    User_Adc_Init();            //ADC

    eeprom_driver_init();       //EEPROM

    rgb_matrix_driver_init();   //PWM DMA 初始化

    Init_Gpio_Infomation();     //GPIO

    Init_Keyboard_Infomation(); //初始化键盘基本信息

    Key_Switch_Mode_Power();    //拨动开关强制切换模式

    Init_Batt_Infomation();     //初始化电池电量

    User_Systime_Init();        //time定时器

    if (Keyboard_Info.Key_Mode == QMK_USB_MODE) {
        User_Usb_Init();        //USB 插件
        Led_Rf_Pair_Flg = false;
    } else {
        Usb_Disconnect();
    }

    Init_Spi_Power_Up = true;
    Init_Spi_100ms_Delay = 0;
    Spi_Interval = SPI_DELAY_RF_TIME;
	NVIC_SetPriority(PendSV_IRQn, 3);
	NVIC_SetPriority(SysTick_IRQn, 3);

    Usb_If_Ok = false;
    Usb_If_Ok_Led = false;
    Led_Power_Up = false;
    Emi_Test_Start = false;

#if LOGO_LED_ENABLE
    Logo_Init();
#endif

#if SIDE_LED_ENABLE
    Side_Init();
#endif
}

void keyboard_post_init_user(void) {
    if (keymap_config.nkro != Keyboard_Info.Nkro) { //全键六键无冲
        keymap_config.nkro = Keyboard_Info.Nkro;
    }

    if (Keyboard_Info.Mac_Win_Mode) {               //MAC系统同步切换图层
        uint8_t current_layer = get_highest_layer(layer_state);
        if (current_layer != 1) {
            layer_on(1);
        }
    }
}

void User_bluetooth_send_keyboard(uint8_t *report, uint32_t len) {
	if(app_2g4_buffer_full()) {     // 队列满直接返回
		return;
	}

    if (len > USER_KEYBOARD_LENGTH - 3) {
        len = USER_KEYBOARD_LENGTH - 3;
    }

    uint8_t Temp_Tx_Buf[USER_KEYBOARD_LENGTH] = {0};

    Temp_Tx_Buf[0] = USER_KEYBOARD_COMMAND;
    Temp_Tx_Buf[1] = USER_KEYBOARD_LENGTH;

    if (len == sizeof(report_keyboard_t)) {     // 六键
        memcpy((void *)&Temp_Tx_Buf[3], report, len);
        Temp_Tx_Buf[2] = USER_KEY_BYTE_DATA;
    } else {
        switch (report[0]) {
            case KB_REPORT_ID: {                // 全键
                memcpy((void *)&Temp_Tx_Buf[3], report, len);
                Temp_Tx_Buf[2] = USER_KEY_BIT_DATA;
                break;
            }
            case SYS_REPORT_ID: {               // 系统键
                memcpy((void *)&Temp_Tx_Buf[3], report, len);
                Temp_Tx_Buf[2] = USER_SYSTEM_DATA;
                break;
            }
            case CON_REPORT_ID: {               // 多媒体键
                memcpy((void *)&Temp_Tx_Buf[3], report, len);
                Temp_Tx_Buf[2] = USER_CONSUMER_DATA;
                break;
            }
            case MOUSE_REPORT_ID: {             // 鼠标
                memcpy((void *)&Temp_Tx_Buf[3], report, len);
                Temp_Tx_Buf[2] = USER_MOUSE_DATA;
                break;
            }
            default: {
                break;
            }
        }
    }

    memcpy(app_2g4_data[app_2g4_data_rev], Temp_Tx_Buf, USER_KEYBOARD_LENGTH);
    app_2g4_buffer_rev_add();
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {   // 键盘只要有按键按下就会调用此函数
    Usb_Change_Mode_Delay = 0;                                      // 只要有按键就不会进入休眠
    Usb_Change_Mode_Wakeup = false;

    switch (keycode) {
        case QMK_KB_MODE_2P4G: {                                    //2.4G
            if (Keyboard_Info.Key_Mode != QMK_2P4G_MODE) {
                return true;
            }
            if (record->event.pressed) {
                Key_2p4g_Status = true;
            } else {
                Key_2p4g_Status = false;
            }
            Time_3s_Count = 0;
        } return true;
        case QMK_KB_MODE_BLE1: {                                    //BLE 1
            if (Keyboard_Info.Key_Mode != QMK_BLE_MODE) {
                return true;
            }
            if (record->event.pressed) {
                Key_Ble_1_Status = true;
                if (Keyboard_Info.Ble_Channel != QMK_BLE_CHANNEL_1) {
                    Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_1;
                    Spi_Send_Commad(USER_SWITCH_BLE_1_MODE);        /*发送SPI命令*/
                    Save_Flash_Set();
                    Led_Rf_Pair_Flg = true;
                }
            } else {
                Key_Ble_1_Status = false;
            }
            Time_3s_Count = 0;
        } return true;
        case QMK_KB_MODE_BLE2: {                                    //BLE 2
            if (Keyboard_Info.Key_Mode != QMK_BLE_MODE) {
                return true;
            }

            if (record->event.pressed) {
                Key_Ble_2_Status = true;
                if (Keyboard_Info.Ble_Channel != QMK_BLE_CHANNEL_2) {
                    Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_2;
                    Spi_Send_Commad(USER_SWITCH_BLE_2_MODE);        /*发送SPI命令*/
                    Save_Flash_Set();
                    Led_Rf_Pair_Flg = true;
                }
            } else {
                Key_Ble_2_Status = false;
            }
            Time_3s_Count = 0;
        } return true;
        case QMK_KB_MODE_BLE3: {                                    //BLE 3
            if (Keyboard_Info.Key_Mode != QMK_BLE_MODE) {
                return true;
            }

            if (record->event.pressed) {
                Key_Ble_3_Status = true;
                if (Keyboard_Info.Ble_Channel != QMK_BLE_CHANNEL_3) {
                    Keyboard_Info.Ble_Channel = QMK_BLE_CHANNEL_3;
                    Spi_Send_Commad(USER_SWITCH_BLE_3_MODE);        /*发送SPI命令*/
                    Save_Flash_Set();
                    Led_Rf_Pair_Flg = true;
                }
            } else {
                Key_Ble_3_Status = false;
            }
            Time_3s_Count = 0;
        } return true;
        case QMK_KB_MODE_USB: {                                     //USB
            if (record->event.pressed) {
                if (Keyboard_Info.Key_Mode != QMK_USB_MODE) {
                    Keyboard_Info.Key_Mode = QMK_USB_MODE;
                    Spi_Send_Commad(USER_SWITCH_USB_MODE);          // 发送SPI命令
                    es_restart_usb_driver();
                    Save_Flash_Set();
                    Led_Rf_Pair_Flg = false;
                }
            }
        } return true;

        case QMK_BATT_NUM: {                                        //电池状态显示
            if (record->event.pressed) {
                User_Key_Batt_Num_Show = true;
                User_Key_Batt_Count = 0;
            } else {
                User_Key_Batt_Num_Show = false;
                User_Key_Batt_Count = 0;
            }
        } return true;

        case QMK_WIN_LOCK: {                                        //锁WIN
            if (!record->event.pressed) {
                if (Keyboard_Info.Mac_Win_Mode == INIT_MAC_MODE) {
                    if (Keyboard_Info.Win_Lock == INIT_WIN_LOCK) {
                        Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
                        Save_Flash_Set();
                    }
                } else {
                    if (Keyboard_Info.Win_Lock == INIT_WIN_NLOCK) {
                        Keyboard_Info.Win_Lock = INIT_WIN_LOCK;
                        unregister_code(KC_LGUI); unregister_code(KC_RGUI); unregister_code(KC_APP);
                    } else {
                        Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
                    }
                    Save_Flash_Set();
                }
            }
        } return true;

        case QMK_KB_SIX_N_CH: {                                     //六键全键无冲切换
            if (record->event.pressed) {
                if(keymap_config.nkro) {
                    es_change_qmk_nkro_mode_disable();
                    Mac_Win_Point_Count = 3;
                } else {
                    es_change_qmk_nkro_mode_enable();
                    Led_Point_Count = 3;
                }
            }
        } return true;

        case KC_LGUI: {                                             //key_win_l
            if (Keyboard_Info.Win_Lock) {
                record->event.pressed = false;
            }
        } return true;

        case KC_RGUI: {                                             //key_win_r
            if (Keyboard_Info.Win_Lock) {
                record->event.pressed = false;
            }
        } return true;

        case KC_APP: {                                              //key_app
            if (Keyboard_Info.Win_Lock) {
                record->event.pressed = false;
            }
        } return true;

        case RGB_VAI: {                                             //亮度加
            if (!record->event.pressed) {
                if (rgb_matrix_get_val() >= RGB_MATRIX_MAXIMUM_BRIGHTNESS) {
                    Led_Point_Count = 3;
                }
            }
        } return true;

        case RGB_VAD: {                                             //亮度减
            if (!record->event.pressed) {
                if (rgb_matrix_get_val() <= 0) {
                    Led_Point_Count = 3;
                }
            }
        } return true;

        case RGB_SPI: {                                             //速度加
            if (!record->event.pressed) {
                if (rgb_matrix_get_speed() >= 255) {
                    Led_Point_Count = 3;
                }
            }
        } return true;

        case RGB_SPD: {                                             //速度减
            if (!record->event.pressed) {
                if (rgb_matrix_get_speed() <= 0) {
                    Led_Point_Count = 3;
                }
            }
        } return true;

        case RGB_RTOG: {                                            //开关闭背光侧灯logo灯
            if (!record->event.pressed) {
                if (Keyboard_Info.Led_On_Off) {
                    // Keyboard_Info.Logo_On_Off = LOGO_LED_ON;
                    Keyboard_Info.Led_On_Off = INIT_LED_ON;
                    Keyboard_Info.Side_On_Off = SIDE_LED_ON;
                    Keyboard_Info.Logo_On_Off = LOGO_LED_ON;
                    if (rgb_matrix_get_val() <= 0) {                // 获取当前指示灯亮度
                        /*设置RGB灯的色相（hue）、饱和度(sat)、亮度*/
                        rgb_matrix_sethsv_noeeprom(rgb_matrix_get_hue(), rgb_matrix_get_sat(), RGB_MATRIX_MAXIMUM_BRIGHTNESS);
                    }
                    if (Keyboard_Info.Side_Brightness <= SIDE_MIN_BRIGHTNESS) {
                        Keyboard_Info.Side_Brightness = SIDE_MAX_BRIGHTNESS;
                    }
                } else {
                    // Keyboard_Info.Logo_On_Off = LOGO_LED_OFF;
                    Keyboard_Info.Led_On_Off = INIT_LED_OFF;
                    Keyboard_Info.Side_On_Off = SIDE_LED_OFF;
                    Keyboard_Info.Logo_On_Off = LOGO_LED_OFF;
                }
                Side_Init();
                Logo_Init();
                Save_Flash_Set();
            }
        } return true;

        case MO(2): {                                               //FN
            if (record->event.pressed) {
                Key_Fn_Status = true;
            } else {
                Key_Fn_Status = false;
            }
        } return true;

        case MO(3): {                                               //FN
            if (record->event.pressed) {
                Key_Fn_Status = true;
            } else {
                Key_Fn_Status = false;
            }
        } return true;

        case TO(0): {                                               //WIN模式下
           if (!record->event.pressed) {
               if ((record->event.key.col == WIN_COL) && (record->event.key.row == WIN_ROL) && (Keyboard_Info.Mac_Win_Mode != INIT_WIN_MODE)) {
                   Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
                   Mac_Win_Point_Count = 1;
                   unregister_code(KC_LALT); unregister_code(KC_LGUI); unregister_code(KC_RALT); unregister_code(KC_RGUI); unregister_code(KC_APP);
                   Save_Flash_Set();
               }
           }
        } return true;

        case TO(1): {                                               //MAC模式下
           if (!record->event.pressed) {
               if ((record->event.key.col == MAC_COL) && (record->event.key.row == MAC_ROL) && (Keyboard_Info.Mac_Win_Mode != INIT_MAC_MODE)) {
                   Keyboard_Info.Mac_Win_Mode = INIT_MAC_MODE;
                   Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
                   Mac_Win_Point_Count = 3;
                   unregister_code(KC_LALT); unregister_code(KC_LGUI); unregister_code(KC_RALT); unregister_code(KC_RGUI); unregister_code(KC_APP);
                   Save_Flash_Set();
               }
           }
        } return true;

        case IOS_SIRI: {                                            //SIRI
            if (record->event.pressed) {
                host_consumer_send(0X0CF);
            } else {
                host_consumer_send(0X000);
            }
        } return true;

        case EE_CLR: {                                              //系统复位
            if (record->event.pressed) {
                Keyboard_Info.Nkro = INIT_ALL_KEY;
                Keyboard_Info.Mac_Win_Mode = INIT_WIN_MODE;
                Keyboard_Info.Win_Lock = INIT_WIN_NLOCK;
                Keyboard_Info.Led_On_Off = INIT_LED_ON_OFF;
            #if LOGO_LED_ENABLE
                Keyboard_Info.Logo_On_Off = INIT_LOGO_ON_OFF;
                Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
                Keyboard_Info.Logo_Colour = INIT_LOGO_COLOUR;
                Keyboard_Info.Logo_Saturation = INIT_LOGO_SATURATION;
                Keyboard_Info.Logo_Brightness = INIT_LOGO_BRIGHTNESS;
                Keyboard_Info.Logo_Speed = INIT_LOGO_SPEED;
                Logo_Init();
            #endif
            #if SIDE_LED_ENABLE
                Keyboard_Info.Side_On_Off = INIT_SIDE_ON_OFF;
                Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
                Keyboard_Info.Side_Colour = INIT_SIDE_COLOUR;
                Keyboard_Info.Side_Saturation = INIT_SIDE_SATURATION;
                Keyboard_Info.Side_Brightness = INIT_SIDE_BRIGHTNESS;
                Keyboard_Info.Side_Speed = INIT_SIDE_SPEED;
                Side_Init();
            #endif
                Reset_Save_Flash = true;
                /*将当前模式写入flash*/
                eeprom_write_block_user((void *)&Keyboard_Info, 0, sizeof(Keyboard_Info_t));
                Reset_Save_Flash = false;
            }
        } return true;

        case U_EE_CLR: {                                             //复位
            if (record->event.pressed) {
                User_QMK_EE_CLR_Flag = true;
            }else{
                User_QMK_EE_CLR_Flag = false;
                Time_3s_EE_CLR_Count = 0;
            }
        } return true;

    #if LOGO_LED_ENABLE
        case LOGO_TOG: {                                            //logo 灯光开关
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off) {
                    Keyboard_Info.Logo_On_Off = LOGO_LED_ON;
                    if (Keyboard_Info.Logo_Brightness <= LOGO_MIN_BRIGHTNESS) {
                        Keyboard_Info.Logo_Brightness = LOGO_MAX_BRIGHTNESS;
                    }
                } else {
                    Keyboard_Info.Logo_On_Off = LOGO_LED_OFF;
                }
                Logo_Init();
                Save_Flash_Set();
            }
        } return true;

        case LOGO_MOD: {                                            //logo 模式切换
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off) {
                    return true;
                } else {
                    if (Keyboard_Info.Logo_Mode < LOGO_OFF_MODE) {
                        Keyboard_Info.Logo_Mode ++;
                    } else {
                        Keyboard_Info.Logo_Mode = INIT_LOGO_MODE;
                    }
                }
                Logo_Init();
                Save_Flash_Set();
            }
        } return true;

        case LOGO_RMOD: {                                           //logo 模式切换
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off) {
                    return true;
                } else {
                    if (Keyboard_Info.Logo_Mode > INIT_LOGO_MODE) {
                        Keyboard_Info.Logo_Mode--;
                    } else {
                        Keyboard_Info.Logo_Mode = LOGO_OFF_MODE;
                    }
                }
                Logo_Init();
                Save_Flash_Set();
            }
        } return true;

        case LOGO_HUI: {                                            //logo 颜色增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE) || (Keyboard_Info.Logo_Mode == LOGO_WAVE_RGB_MODE) || (Keyboard_Info.Logo_Mode == LOGO_SPECTRUM_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Logo_Colour < (LOGO_MAX_COLOUR - COLOUR_LEVEL)) {
                        Keyboard_Info.Logo_Colour += COLOUR_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Colour = ((Keyboard_Info.Logo_Colour + COLOUR_LEVEL) - LOGO_MAX_COLOUR);
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_HUD: {                                            //logo 颜色减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE) || (Keyboard_Info.Logo_Mode == LOGO_WAVE_RGB_MODE) || (Keyboard_Info.Logo_Mode == LOGO_SPECTRUM_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Logo_Colour - COLOUR_LEVEL) > LOGO_MIN_COLOUR) {
                        Keyboard_Info.Logo_Colour -= COLOUR_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Colour = ((LOGO_MAX_COLOUR - COLOUR_LEVEL) + Keyboard_Info.Logo_Colour);
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_SAI: {                                            //logo 饱和度增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Logo_Saturation - SATURATION_LEVEL) > LOGO_MAX_SATURATION) {
                        Keyboard_Info.Logo_Saturation -= SATURATION_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Saturation = LOGO_MAX_SATURATION;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_SAD: {                                            //logo 饱和度减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Logo_Saturation < (LOGO_MIN_SATURATION - SATURATION_LEVEL)) {
                        Keyboard_Info.Logo_Saturation += SATURATION_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Saturation = LOGO_MIN_SATURATION;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_VAI: {                                            //logo 亮度增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Logo_Brightness < (LOGO_MAX_BRIGHTNESS - BRIGHTNESS_LEVEL)) {
                        Keyboard_Info.Logo_Brightness += BRIGHTNESS_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Brightness = LOGO_MAX_BRIGHTNESS;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_VAD: {                                            //logo 亮度减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Logo_Brightness - BRIGHTNESS_LEVEL) > LOGO_MIN_BRIGHTNESS) {
                        Keyboard_Info.Logo_Brightness -= BRIGHTNESS_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Brightness = LOGO_MIN_BRIGHTNESS;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_SPI: {                                            //logo 速度增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Logo_Speed < (LOGO_MAX_SPEED - SPEED_LEVEL)) {
                        Keyboard_Info.Logo_Speed += SPEED_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Speed = LOGO_MAX_SPEED;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case LOGO_SPD: {                                            //logo 速度减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Logo_On_Off || (Keyboard_Info.Logo_Mode == LOGO_OFF_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Logo_Speed - SPEED_LEVEL) > LOGO_MIN_SPEED) {
                        Keyboard_Info.Logo_Speed -= SPEED_LEVEL;
                    } else {
                        Keyboard_Info.Logo_Speed = LOGO_MIN_SPEED;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;
    #endif
    #if SIDE_LED_ENABLE
        case SIDE_TOG: {                                            //侧灯 灯光开关
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off) {
                    Keyboard_Info.Side_On_Off = SIDE_LED_ON;
                    if (Keyboard_Info.Side_Brightness <= SIDE_MIN_BRIGHTNESS) {
                        Keyboard_Info.Side_Brightness = SIDE_MAX_BRIGHTNESS;
                    }
                } else {
                    Keyboard_Info.Side_On_Off = SIDE_LED_OFF;
                }
                Side_Init();
                Save_Flash_Set();
            }
        } return true;
        
        case SIDE_MOD: {                                            //侧灯 模式切换
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off) {
                    return true;
                } else {
                    if (Keyboard_Info.Side_Mode < SIDE_OFF_MODE) {
                        Keyboard_Info.Side_Mode ++;
                    } else {
                        Keyboard_Info.Side_Mode = INIT_SIDE_MODE;
                    }
                }
                Side_Init();
                Save_Flash_Set();
            }
        } return true;

        case SIDE_RMOD: {                                           //侧灯 模式切换
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off) {
                    return true;
                } else {
                    if (Keyboard_Info.Side_Mode > INIT_SIDE_MODE) {
                        Keyboard_Info.Side_Mode--;
                    } else {
                        Keyboard_Info.Side_Mode = SIDE_LIGHT_MODE;
                    }
                }
                Side_Init();
                Save_Flash_Set();
            }
        } return true;

        case SIDE_HUI: {                                            //侧灯 颜色增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE) || (Keyboard_Info.Side_Mode == SIDE_WAVE_RGB_MODE) || (Keyboard_Info.Side_Mode == SIDE_SPECTRUM_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Side_Colour < (SIDE_MAX_COLOUR - SIDE_COLOUR_LEVEL)) {
                        Keyboard_Info.Side_Colour += SIDE_COLOUR_LEVEL;
                    } else {
                        Keyboard_Info.Side_Colour = ((Keyboard_Info.Side_Colour + SIDE_COLOUR_LEVEL) - SIDE_MAX_COLOUR);
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_HUD: {                                            //侧灯 颜色减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE) || (Keyboard_Info.Side_Mode == SIDE_WAVE_RGB_MODE) || (Keyboard_Info.Side_Mode == SIDE_SPECTRUM_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Side_Colour - SIDE_COLOUR_LEVEL) > SIDE_MIN_COLOUR) {
                        Keyboard_Info.Side_Colour -= SIDE_COLOUR_LEVEL;
                    } else {
                        Keyboard_Info.Side_Colour = ((SIDE_MAX_COLOUR - SIDE_COLOUR_LEVEL) + Keyboard_Info.Side_Colour);
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_SAI: {                                            //侧灯 饱和度增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Side_Saturation - SIDE_SATURATION_LEVEL) > SIDE_MAX_SATURATION) {
                        Keyboard_Info.Side_Saturation -= SIDE_SATURATION_LEVEL;
                    } else {
                        Keyboard_Info.Side_Saturation = SIDE_MAX_SATURATION;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_SAD: {                                            //侧灯 饱和度减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Side_Saturation < (SIDE_MIN_SATURATION - SIDE_SATURATION_LEVEL)) {
                        Keyboard_Info.Side_Saturation += SIDE_SATURATION_LEVEL;
                    } else {
                        Keyboard_Info.Side_Saturation = SIDE_MIN_SATURATION;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_VAI: {                                            //侧灯 亮度增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Side_Brightness < (SIDE_MAX_BRIGHTNESS - SIDE_BRIGHTNESS_LEVEL)) {
                        Keyboard_Info.Side_Brightness += SIDE_BRIGHTNESS_LEVEL;
                    } else {
                        Keyboard_Info.Side_Brightness = SIDE_MAX_BRIGHTNESS;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_VAD: {                                            //侧灯 亮度减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Side_Brightness - SIDE_BRIGHTNESS_LEVEL) > SIDE_MIN_BRIGHTNESS) {
                        Keyboard_Info.Side_Brightness -= SIDE_BRIGHTNESS_LEVEL;
                    } else {
                        Keyboard_Info.Side_Brightness = SIDE_MIN_BRIGHTNESS;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_SPI: {                                            //侧灯 速度增加
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE)) {
                    return true;
                } else {
                    if (Keyboard_Info.Side_Speed < (SIDE_MAX_SPEED - SIDE_SPEED_LEVEL)) {
                        Keyboard_Info.Side_Speed += SIDE_SPEED_LEVEL;
                    } else {
                        Keyboard_Info.Side_Speed = SIDE_MAX_SPEED;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;

        case SIDE_SPD: {                                            //侧灯 速度减小
            if (!record->event.pressed) {
                if (Keyboard_Info.Side_On_Off || (Keyboard_Info.Side_Mode == SIDE_OFF_MODE)) {
                    return true;
                } else {
                    if ((Keyboard_Info.Side_Speed - SIDE_SPEED_LEVEL) > SIDE_MIN_SPEED) {
                        Keyboard_Info.Side_Speed -= SIDE_SPEED_LEVEL;
                    } else {
                        Keyboard_Info.Side_Speed = SIDE_MIN_SPEED;
                        Led_Point_Count = 3;
                    }
                }
                Save_Flash_Set();
            }
        } return true;
    #endif
        default:    return true;    // 正常处理其他所有键码
    }
}
